當想要佈署的 docker container 超過一個以上時,會突然發現 docker run 這個指令打到手軟,特別是當要跑起來的容器還要掛載一堆本地端資料夾,一直寫 -v /home/.../.../HostData1:/home/mountData -v /home/.../HostData2:/home/mountData2 簡直是記憶力大考驗。這時候就是拿出 Docker Compose 這個工具的時候了~~
什麼時候要使用 docker compose
- 想要利用一份檔案管理多個 docker container 時。
- 希望多個 docker container 彼此之間有所關聯時 (例如都在同一個網路內且大家都看得到對方)。
- 希望建立類似 CI workflows,可以用來開發、測試、與建立 staging 環境。
安裝 docker compose
- 在 Windows 環境下
- 當安裝完 docker 桌面版應用程式後,docker compose 工具也一併安裝完成
- 在 Ubuntu 環境下
- 安裝需要使用 curl 工具,可以參考 How To Install Docker Compose On Ubuntu 18.04
- docker compose 也可以直接使用 pip 安裝
pip3 install docker-compose
流程
- 使用 Dockerfile 確定你的服務環境和所需套件。
- 使用 docker-compose.yml 定義你的服務範圍,以及他們在 docker 環境內彼此的關係。
- 執行 docker-compose up,此時會依據 docker-compose.yml 文件內的描述開始執行整個 docker 環境和服務的建構。
docker compose 基本內容
- docker-compose.yml
- 用來定義 docker 環境及所有服務彼此之間的關係
- command
- docker-compose up -d
會將 docker-compose.yml 裡所有定義的服務一起啟動,流程包括- 先開創一個共同的網路,預設名稱為 {docker-compose.yml 所在的資料夾名稱}_default
- 依序啟動各個服務,並將每個服務加入至此預設網路內
- 後面加上 -d 參數代表 detach,跟 docker run -d 一樣意思
- docker-compose down
依序關閉每個服務,最後將預設的網路停止 - docker-compose ps
查看 Docker Container 的執行狀態
- docker-compose up -d
- 縮排規定要空白鍵,而不是 tab。
docker-compose.yml 範例
研究 docker-compose 是因為我在目前的專案上有一些需求 (暫時稱呼我的專案叫作專案A好了),包括:
- 需要利用 docker 建立兩個 container,一個跑專案 A 的 server,一個跑 redis server
- A_server 跑 Django 框架,且需在本地端 build image
- A_server 需要掛載本地端的資料夾到容器內
- A_server 需要看得到 redis_server
- 兩個容器可以一起管理
依照我自己的需求我製作了以下的 docker-compose.yml 檔案
version: '3'
services:
A_server:
build: .
depends_on:
- redis_server
ports:
- "8000:8000"
volumes:
- ./AWebCode1:/home/smart/AWebCode1
- ./AwebCode2:/home/smart/AWebCode2
restart: always
container_name: servicebox
redis_server:
image: redis:latest
ports:
- "6379:6379"
restart: always
container_name: redis_box
我們來看一下上面這份檔案
- 第一行 version 一定要寫。
- services 定義所有的容器內容及相關細項,這裡定義了兩個容器,包括 A_server 和 redis_server。
- 對於 A_server 來說
- 因為需要在本地端編譯成 docker image,所以使用 build。後面使用 . 代表直接在 docker-compose.yml 這份檔案的所在地直接找尋 dockerfile 然後開始做編譯
- depends_on 後面接 redis_server,代表當容器啟動時,會先將 redis_server 的容器啟動後再啟動 A_server 的容器
- ports 這邊指明 8000:8000 的對映關係,就跟 docker run -p 8000:8000 一樣意思
- volumes 這邊指定需要掛載本地端到容器內的資料夾,就跟 docker run -v aaa:bbb 一樣意思,甚至這邊可以掛載多個還可以一次寫滿寫好
- container_name 可以指定當容器啟動時的預設名稱
- 對於 redis_server 來說
- 因為直接使用 docker registry 上面的 image,所以可以直接利用 image 關鍵字指定需要 docker pull 的 image 名稱和 tag
- 還記得在使用 docker run -v 的時候,後面的資料夾必須寫完整路徑嗎?但是在 docker-compose 檔案裡可以使用相對路徑,是不是很方便?
- 如果 docker-compose 裡沒有特別指定網路的話,則會自動建立一個 default 網路,然後把兩個 service 都加入到此網路中,重點是他們要怎麼認到彼此呢?請記得在這個網路中,定義好的 service name 會自動代換成他們在這個網路中的 DNS name,因此對於 A_server 這個 container 來說,只要在網址列輸入 http://redis_server 就可以連到 redis_server 這個容器,相反的從 redis_server 要連到 A_server 也是一樣的道理。
這次的重點整理
- 由於我這次的專案主要是使用 Django 框架,而在 Django 的 settings 裡面應該要設定 redis server 的 url,原本我是寫 127.0.0.1 然後永遠連不到,現在知道要直接寫 yml 檔裡的 redis server 的名稱。以這個範例來說,要在 settings 裡面寫的 url 是 redis_server 這個字串。
- 使用 docker-compose 工具最明顯的優點
- 設定檔可以使用相對路徑
- 可以先寫好多個掛載點,不用每次 docker run 時再慢慢輸入
- 可以建立容器之間的共同橋樑
Reference
Day 24:使用 Docker-Compose 啟動多個 Docker Container
Build a Multi-Container Docker Application with Docker Compose with a React, Node, and Postgres App
Docker Compose 初步閱讀與學習記錄
透過 Docker Compose 設定 network
官方快速教學範例
Docker Compose 配置檔案 Docker-Compose.yml 檔案詳解