iT邦幫忙

2023 iThome 鐵人賽

0
Software Development

救救我啊我救我!CRUD 工程師的惡補日記系列 第 38

【Docker】利用 Docker Compose 完成多容器部署(一)

  • 分享至 

  • xImage
  •  

一個系統至少有前端、後端、資料庫等部件要運行。若還進一步切分成微服務,或導入其他軟體(如訊息佇列、全文檢索引擎),那麼就必須下好幾個指令來啟動這些容器。在廣泛使用 Docker 的團隊,不論是在各個環境部署,或者工程師本地開發,這一點將是個麻煩的地方。

本文介紹 Docker Compose,我們可將原本啟動容器時要用的參數,集中寫在一個檔案。最後只要執行一個 Docker 指令,便能一併啟動所有容器,十分便利。

此篇亦轉載到個人部落格


一、認識 Docker Compose 配置檔

本節筆者以 MySQL 資料庫為對象,示範如何使用 Docker Compose。

(一)配置檔概觀

回顧一下當初建立 MySQL 容器時,Docker 指令是如何寫的。以下是個簡單的例子,指定了映像檔來源、容器的名稱、port 號,以及環境變數。

docker container create -p 3306:3306 --name DemoMySQL -e MYSQL_ROOT_PASSWORD=000000 mysql:8.2.0

請準備一個資料夾,當作 compose 的根目錄,筆者取名為「my-project」。接著在裡面建立叫做「docker-compose.yml」的檔案,它是 Docker Compose 的配置檔。這個副檔名「yml」的檔案,叫做「yaml」檔。其內容是有階層之分的,並以兩個空格為縮排。

請在配置檔撰寫如下的內容,我們再逐一認識它們。

services:
  db:
    image: mysql:8.2.0
    container_name: DemoMySQL
    ports:
      - 3306:3306
    environment:
      - MYSQL_ROOT_PASSWORD=000000
      - MYSQL_USER=user
      - MYSQL_PASSWORD=123456
      - MYSQL_DATABASE=demo

仔細觀察,可發覺這些內容其實就是將 Docker 建立容器的參數寫上去,讓人一目了然。

(二)參數介紹

在配置檔的 services 階層下,可撰寫各個容器的相關參數。我們用「service」來稱呼一個提供服務的容器。

上面的例子提供了 MySQL 的參數,另外也給服務取名(必須是小寫),此處取名為「db」。服務名稱可用於 Docker Compose 的一些指令,或是在配置檔中做為 key 來指向。

在服務名稱底下的階層,可撰寫建立容器的參數。
|| Docker Compose 參數 || 意義 || 對應 docker run 指令參數 ||
|-|-|-|
| image | 映像檔名稱 |(寫在最後面)|
| container_name | 容器名稱 | --name |
| port | port 的轉發(左邊為主機的 port 號,而右邊是容器) | -p |
| environment | 環境變數 | -e |

其中像 portenvironment 這種有一至多個項目的參數,會用 - 符號加一個空格來列項。

二、啟動 Compose

寫好 docker-compose.yml 配置檔後,就能透過指令來啟動容器了。

(一)啟動

啟動 compose 的指令寫法為 docker compose -f {配置檔名稱} up -d

Docker 會在 command line 當前的路徑下讀取名為「docker-compose.yml」的檔案。若讀者取了其他名稱,請用 -f 參數來指定。而加上 -d 選項則是讓 Docker Compose 在背景運行。

假設我們已經位於該配置檔的所在路徑(如本文的「my-project」資料夾),則啟動的範例指令如下。

docker compose up -d

執行後,配置檔中描述的容器便會一一啟動。此時再執行 docker container ls 指令,讀者也能看見目前運行中的容器。

這個 docker compose up 指令,相當於在背後執行了多個 docker container run。當映像檔不存在時,會先從 Docker Hub 下載回來。若容器名稱重複,或是 port 號被佔用,Docker 也會顯示錯誤訊息。

(二)異動配置檔

接下來讓我們在配置檔中,添加第二個服務。此處以訊息佇列 RabbitMQ 為例,並給予服務名稱「mq」。

services:
  db:
    # ...
  mq:
    image: rabbitmq:3.12.4-management
    container_name: DemoRabbitMQ
    ports:
      - 5672:5672
      - 15672:15672
    environment:
      - RABBITMQ_DEFAULT_USER=user
      - RABBITMQ_DEFAULT_PASS=123456

執行 docker compose up 指令後,可發現 RabbitMQ 的容器跑起來了。而既有的 MySQL 容器持續運行著,不會被中斷。

若讀者隨意更改一下 MySQL 的參數(例如環境變數),並再執行一次,則原本的容器就會被刪除,重新建立新的。

三、操作 Compose 服務

現在這個 compose 中有兩個服務,在配置檔中分別取名為「db」與「mq」。服務的名稱可用於 docker compose 的相關指令,本節就來認識其中幾個。

(一)停止

使用 docker compose stop 指令,可停止 compose 中的所有服務。

若加上服務名稱,則是停止指定的服務,範例指令如下:

docker compose stop db

(二)移除

使用 docker compose down 指令,可移除整個 compose。

若加上服務名稱,則是移除指定的服務,範例指令如下:

docker compose down db

如果 compose 中的服務均被移除,則 compose 本身也將被移除。

(三)啟動

使用 docker compose start 指令,可啟動 compose 中的所有服務。

若加上服務名稱,則是啟動指定的服務,範例指令如下:

docker compose start db

這個指令與 docker compose up 的不同之處,在於「up」會讀取配置檔的參數,重新建立 compose。而「start」純粹是啟動,配置是沿用原本的。

此外,如果 compose 曾經有服務被移除,那這個指令是不會啟動該服務的。

(四)查看 Log

使用 docker compose logs 指令,可查看 compose 中所有服務的的 log。
docker-compose-logs.png
https://ithelp.ithome.com.tw/upload/images/20231218/20131107fbJ26qyPT6.png

若加上服務名稱,則是查看指定的服務,範例指令如下:

docker compose logs -f db

讀者也能加上 -f 選項,讓 command line 上顯示的 log 能即時更新。

四、從外部帶入環境變數

配置檔中的「db」與「mq」這兩個服務,都有各自的環境變數。然而一個產品在不同環境運行時,所需要的環境變數也不盡相同,例如連線的帳密。

此時讀者有兩種選擇,一種是撰寫不同的配置檔,將變數值都寫死(hard code)。另一種是本節要介紹的,透過外部檔案來帶入變數值。

請在 compose 的根目錄或其子資料夾下,建立兩個副檔名為「.env」的檔案,而主檔名隨意,方便辨識即可。用途是分別存放 MySQL 與 RabbitMQ 的環境變數。以下範例為目前的檔案相對位置。

my-project
  |_ docker-compose.yml
  |_ service-env-files
      |_ mysql.env
      |_ rabbitmq.env

請在「mysql.env」檔案寫入以下參數。

MYSQL_ROOT_PASSWORD=000000
MYSQL_USER=user
MYSQL_PASSWORD=123456
MYSQL_DATABASE=demo

也在「rabbitmq.env」檔案寫入以下參數。

RABBITMQ_DEFAULT_USER=user
RABBITMQ_DEFAULT_PASS=123456

最後調整配置檔的內容,將「environment」這個階層,以「env_file」取代,並分別提供 env 檔案的路徑。

services:
  db:
    # ...
    env_file: ./service-env-files/mysql.env
  mq:
    # ...
    env_file: ./service-env-files/rabbitmq.env

修改完成後,可執行 docker compose config 指令,觀看配置檔會被解讀成什麼樣子。除了確認帶入的變數是否正確,且若能看見內容,也意味著配置檔的格式沒有問題。

如此一來,我們可藉由抽換 env 檔案,來提供不同的環境變數。

本文主要是讓讀者初步認識 Docker Compose,體會一次啟動多個容器的便利。下一篇會介紹更深入的配置,包含 Dockerfile、掛載、服務之間的相依,以及定義健康狀態。


今日文章到此結束!
最後宣傳一下自己的部落格,我是「新手工程師的程式教室」的作者,主要發表後端相關文章,請多指教/images/emoticon/emoticon41.gif


上一篇
【Docker】撰寫 Dockerfile 製作映像檔(以 Spring Boot 為例)
下一篇
【Docker】利用 Docker Compose 完成多容器部署(二)
系列文
救救我啊我救我!CRUD 工程師的惡補日記50
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言