# Docker 第二週 本週課程要點 - 上週複習 - 在雲服務上面開機器 - 關於 buildX - Docker Network ## 1. 上週複習 - 如何選用合適的 Docker Image(Nginx 為例) - 如何檢視一個運行中的容器(用什麼指令?) - 如何與容器產生交互狀態 - 如何停止容器,以及關閉所有 exited 狀態中的容器 - 產生 docker image 會使用哪一種檔案 ## 2. 在雲服務上面開機器 ### 雲服務小知識 - IaaS、CaaS、PaaS:https://cloud.google.com/learn/paas-vs-iaas-vs-saas?hl=zh-tw ![image](https://hackmd.io/_uploads/H1v0FkPNC.png) - Region:https://aws.amazon.com/tw/about-aws/global-infrastructure/regions_az/ ![image](https://hackmd.io/_uploads/H1pT5JDV0.png) --- Linode / Akamai 價格表:https://www.linode.com/pricing/ 優點: - 可以預先儲值、價格不會爆表 - 單純簡單(相對於大型雲服務廠商,設置簡單很多 ### 2-1 常見 Linux 指令 1. **切換目錄 (`cd`)**: - 切換到家目錄:**`cd ~`** - 切換到上一層目錄:**`cd ..`** - 切換到根目錄:**`cd /`** 2. **列出檔案和目錄 (`ls`)**: - 列出當前目錄:**`ls`** - 列出當前目錄包括隱藏檔案:**`ls -a`** - 列出詳細資訊:**`ls -l`** 3. **建立和刪除目錄 (`mkdir` 和 `rmdir`)**: - 建立目錄:**`mkdir new_folder`** - 刪除空目錄:**`rmdir old_folder`** 4. **建立、查看和刪除檔案 (`touch`, `cat`, `rm`)**: - 建立新檔案:**`touch file.txt`** - 查看檔案內容:**`cat file.txt`** - 刪除檔案:**`rm file.txt`** 5. **複製和移動/重新命名檔案 (`cp` 和 `mv`)**: - 複製檔案:**`cp source.txt destination.txt`** - 移動或重新命名檔案:**`mv oldname.txt newname.txt`** 6. **查找檔案 (`find`)**: - 在當前目錄下查找檔案:**`find . -name "file.txt"`** 7. **編輯檔案 (`nano`, `vi`)**: - 使用 nano 編輯器:**`nano file.txt`** - 使用 vi 編輯器:**`vi file.txt`** (👉 注意重點補充 👈) ### 2-2 安裝 Docker https://docs.docker.com/engine/install/ubuntu/ ### 2-3 **Docker 服務的開關控制指令** systemctl 是系統層面的指令 1. **啟動 Docker 服務**: ```bash sudo systemctl start docker ``` 2. **停止 Docker 服務**: ```bash sudo systemctl stop docker ``` 3. **重啟 Docker 服務**: ```bash sudo systemctl restart docker ``` 4. **查看 Docker 服務狀態**: ```bash sudo systemctl status docker ``` 5. **設定 Docker 服務開機自啟**: ```bash sudo systemctl enable docker ``` 6. **取消 Docker 服務開機自啟**: ```bash sudo systemctl disable docker ``` ## 3. Docker Hub https://hub.docker.com/ 登入 Docker Hub 可以上傳自己的 image **上傳方式** - 建立 image 名稱為 {account}/{image name} ```docker docker build -t casper723/2024-node-course-express-sample . ``` - 使用 push 指令 ```docker docker image push casper723/2024-node-course-express-sample ``` **下載 image** - 可以直接使用 run,或者使用 pull ```docker docker image pull casper723/2024-node-course-express-sample ``` #### 多架構 使用 buildX:https://docs.docker.com/reference/cli/docker/buildx/ - 如果是安裝 Docker Desktop 會自動安裝 BuildX - Linux 環境下,則需要另外安裝 BuildX 關於 AMD64 與 ARM64 - **`amd64`** 是由 AMD 開發的 64 位元處理器架構,基於擴展的 x86 指令集。這種架構也被 Intel 採用並稱為 Intel 64 或 x86-64,是當前最普遍使用的個人電腦處理器架構。 - **`arm64`** 是 ARM 架構的 64 位元版本,專為低功耗環境設計,廣泛應用於移動設備、嵌入式系統、以及越來越多的桌面和伺服器硬體。 ### 3-1 BuildX **列出所有可用架構** ```docker docker buildx ls ``` **建構多架構的 image** ```docker docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 -t casper723/2024-node-course-express-sample:latest . --push ``` 初次使用時會出錯,會說明當前不能建構多平台,因此需要先建立新的環境(builder)才能運行。 ``` docker buildx create --name multi-arch-builder --use ``` > 常見 builder 命名方式 #### **1. 用途描述** 如果構建器是為了特定的應用或環境設計,名稱中可以包含相關的描述,例如: - **`web-app-builder`** - **`android-ci-builder`** - **`production-release-builder`** #### **2. 平台特定** 如果構建器是為了特定的運行平台或硬體架構而設計,可以在名稱中體現這一點,如: - **`arm64-builder`** - **`linux-amd64-builder`** - **`multi-arch-builder`** 正式打包上傳: ``` docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 -t casper723/2024-node-course-express-sample:latest . --push ``` ### 補充加入版本號的手法 ``` docker build -t myapp:1.0.0 -t myapp:1.0 -t myapp:latest . ``` ## 4. 關於 Network ### 4-1 創建一個專案,需包含 MongoDB(本地端範例) 範例:https://github.com/Wcc723/docker-express-sample-mongo 準備專案及建立 mongo image ```docker docker image pull mongo:latest docker run -d -p 27017:27017 mongo:latest ``` 實作項目: 1. 使用本地端的 Node.js 連接 MongoDB 2. 使用 Docker Container 的 Node.js 連接 MongoDB => 這個會出錯 #### 為什麼會這樣? 原因: 1. 當都屬於容器化時,不能直接連線 localhost(所在 local 已經改變) 2. 容器化時,network 需要另外設定,docker container inspect CONTAINER 查看兩個容器 3. mongoDB 沒有正確命名,node 無法直接取用 ### 4-2 解方一:使用 ip 進行連接 > 了解原理 1. 請先關閉當前所有容器,僅保留 mongoDB 2. 建立兩個 node 輕量型服務(這是簡易說明,只要可以使用部分網路指令即可 1. `docker container run -d --name node2 -p 3001:3000 casper723/2024-node-course-express-sample` 2. `docker container run -d --name node1 -p 3000:3000 casper723/2024-node-course-express-sample` 3. 與這兩個容器產生交互 1. docker container exec -it node1 sh 2. docker container exec -it node2 sh 4. 分別了解當前的狀態 - 做以下幾件事 1. ip a → 取得自己的 ip 2. ping 172.17.0.1 (Gateway) 3. ping 另一台 node 4. ping node2 5. docker container inspect MONGODB 6. ping MONGODB 6. 移除其他 node 容器,mongoDB 連線改用 ip ### 4-3 解方二:實戰建議的解法 Network Bridge > DNS 解析限制:在預設的 bridge 網絡中,Docker 不提供自動的 DNS 解析服務來允許容器透過名稱互相通訊。要啟用這種名稱解析,您需要建立一個使用者定義的網絡(比如 docker network create),這會自動設定 DNS 解析,容器名稱即可用於互相通訊。 #### 建立 Bridge 了解觀念: 1. 建立新的 network ```docker docker network create my-network docker network ls ``` 2. 建立兩個 node 服務,並套用相同 network 1. docker run -d --name node1 --network my-network -p 3000:3000 casper723/2024-node-course-express-sample docker run -d --name node2 --network my-network -p 3001:3000 casper723/2024-node-course-express-sample 3. 使用 inspect 檢視 node1 4. 分別進入兩個容器 1. docker container exec -it node1 sh docker container exec -it node2 sh - 做以下幾件事 1. ip a → 取得自己的 ip 2. ping 172.17.0.1 (Gateway) 3. ping 另一台 node 4. ping node2 (在此可以用 CONTAINER NAME 5. docker container inspect MONGODB 6. ping MONGODB(無法存取另一個 network 的容器 #### 正確使用 Network 建立 MongoDB 1. 建立新的 network - docker network create my-network 2. 創建新容器並連接 network 1. **在此的 mongoDB 沒有對外 port** 2. node 是使用 mongoDB Container name 進行連接 3. 兩個是共用 network ```docker docker run -d --name my-mongodb --network my-network mongo:latest docker run -d -p 3000:3000 -e MONGODB_URL=mongodb://my-mongodb/mydatabase --network my-network casper723/2024-node-course-express-mongo ``` 沒有正確連線時的除錯: - 兩者是否有相連同一個 network - docker network inspect my-network - 容器是否出錯 - docker container inspect CONTAINER 其他補充: #### --restart 參數選項 - no:容器退出後不會重啟。這是默認行為。 - always:無論退出代碼是什麼,總是重啟容器。這包括正常退出(退出代碼為0)的情況。 - unless-stopped:容器只要沒有被手動停止,無論退出代碼是什麼,都會重啟。如果容器被手動停止,則不會重啟。 ## 最後:請在雲服務上重新建構一次