--- title: 【軟體】Docker 基本操作 tags: TTennis Pickup Robot disqus: hackmd --- <h1 style="text-align: center; color: orange;"> 🛠️ 【軟體】必學的 Docker 🛠️ </h1> <h2 style="text-align: center; color: skyblue;">Docker 基本操作</h2> <h3><font color ="magenza"> 1. 安裝</font></h3> * Windows: 安裝 [Docker Desktop](https://www.docker.com/products/docker-desktop/)。 * Linux:不同發行版安裝 Docker 的方式略有差異,自行解決 ~ 安裝完成可輸入 `docker images` 檢查是否正常運作。 </br> <h3><font color ="magenza"> 2-1. 開發流程說明</font></h3> 接下來,會 runthrough 下方四個步驟,來模擬開發流程。 1. 先將官方 ubuntu 22.04 的 image `pull` 到本地端,然後 `run` image。 2. 將生成環境的步驟紀錄在 `.Dockerfile` 裡面。 3. 環境建置完後, `build` 生成新映像檔案。 4. 將新 image `push` 到 docker hub。 </br> <h3><font color ="magenza"> 2-2.下載映像檔 - docker pull </font></h3> `docker pull ubuntu:22.04`:下載 Ubuntu Image。 ![image](https://hackmd.io/_uploads/BJzstOvcA.png =80%x) 這些映像檔(Image)都被存儲在 [Docker Hub](https://hub.docker.com/_/ubuntu) 上。 ![image](https://hackmd.io/_uploads/B1Pxq_wcA.png =80%x) </br> <h3><font color ="magenza"> 2-3.執行 Image 實例 - docker run </font></h3> > docker run 會根據選定的 image 啟動容器。 我們也會在這個實例化的 container 中開發。 通常,container 並不希望被保留下來。 在開發時,我們須要將「改變環境」的事情紀錄在 DockerFile 中 (當然是在確認安裝沒問題後)。例如:`sudo apt install`、`sudo apt remove` 等等。 結束開發再透過 `build` 指令去按照新的 `DockerFile` 構建出新的 image。 下次我們 `run` 新的 image 時,就不需要再重新安裝 pkg。 --- 用 `docker images` 查詢 Image ID 後輸入 `docker run` 指令。 這條命令將會啟動容器,當前終端機將被放到容器內的 bash shell 中。 ```py= # docker run -it --name [容器名稱] [Image ID] /bin/bash docker run -it --name my_container 04682f0e2687 /bin/bash ``` :::spoiler 參數說明 - `-it` :`-i` 保持標準輸入開放,`-t` 分配一個(偽)終端機。 - `-- name`:container 名稱。 - `/bin/bash`:開啟一個交互式 bash shell。 ::: :::info 開容器就像在跑 App,參數 /bin/bash 的用意是去運行終端機這個程序,不然預設是不做任何事情的,run 完就會立刻 shutdown。 ::: </br> <h3><font color ="magenza"> 2-4. 在 Container 中開發環境 - docker exec </font></h3> 在 VSCode 中安裝 remote-development 和 docker 的擴充模組。 `F1` 並輸入 `attach`,選擇「Attach to Running Container …」即可。 :::spoiler 相關指令 * 停止 container 運作:在終端機中 `ctrl+D` 即可。 * 重啟 container: 1. 輸入 `docker ps -a` 查看容器列表。 2. 先 `docker start [CONTAINER_ID]`。 * 運行 container: 1. `docker exec -it [CONTAINER_ID] /bin/bash`。 ::: </br> 進入 Container 後,可以嘗試安裝些簡單的東西。 像是 `apt-get update && apt-get install -y sudo net-tools ssh`。 修改完環境後,確認都沒問題就能記錄在 `Dockerfile`,注意檔名一致。 ```dockerfile= # 基於哪個已存在的 Image 檔案建置環境 FROM ubuntu:22.04 # 終端機指令 RUN apt-get update && \ apt-get install -y apt-utils sudo net-tools ssh ``` </br> <h3><font color ="magenza"> 2-5. 構建新映像檔 - docker build </font></h3> 瀏覽至 Dockerfile 所屬資料夾中,輸入 build 指令。 ```= docker build -t ubuntu:22.04_ver2 --no-cache . ``` :::spoiler 參數說明 * `-t`:新生成的 `[IMAGE_NAME]:[IMAGE_TAG]` * `--no-cache`:建構映像檔時不使用 cache。 這將確保每一步都重新執行。 這會比較耗時間,預設是找出和 base Image 不同之處並修改。 但有時可能會有錯誤,這時就會希望全部重建。 * `.`:`Dockerfile` 路徑。 在當前資料夾開的終端機只需打 `.`,或是貼上完整路徑也可以。 ::: </br> 構建完成後一樣可用 `docker images` 檢查是否有新的 Image。 接著就自己測試以新的 Image 去 run 新的容器,會發現已經有剛剛安裝的 pkg。 </br> --- <h3><font color ="magenza"> 3-1. docker compose 介紹</font></h3> :::info docker build 或 docker run 時常常須要加參數於命令行,我們可以把這些參數寫在 docker-compose.yaml 中,以 `docker compose build/run` 簡化之。 ::: 各版本安裝方式略有不同,自行解決 ~ </br> <h3><font color ="magenza"> 3-2. compose build 文件</font></h3> 這個 **`docker-compose.yaml`** 文件定義了一個名為 **`ros2_service`** 的服務 該服務的 image 將從當前目錄下的 **`Dockerfile`** 進行構建。 並且一旦構建完成該 image 會被 tag 為 **`ros2:humble-core`**。 ```dockerfile= # services 定義要運行的所有容器(或稱服務)。 services: ros2_service: # 定義第一個服務(或容器)的名稱 build: # 定義如何 build context: . # 指定 Dockerfile 的路徑。 dockerfile: Dockerfile # Dockerfile 文件名 image: ros2:humble-core # image 會關聯到以下兩個: # (1) docker compose build 的 [Image][repo:tag]。 # (2) docker compose up 生成容器所根據的 [Image][repo:tag] ``` 此時只需要在 `docker-compose.yaml` 之資料夾層級中: * `docker compose build`:build image。 * `docker compose up`:啟動 container。 * `docker compose down`:結束 container。 </br> <h3><font color ="magenza"> 3-3. compose run 文件</font></h3> 延續剛剛的 yml 文件,多配置一些 run 的參數。 docker 會自己判定 build 和 run 時需要什麼參數。 ```dockerfile= services: ros2_service: build: context: . dockerfile: Dockerfile image: ros2:humble-arm64 container_name: env_devel ## hang in /bin/bash command: /bin/bash tty: true ``` </br>