skip to content
鰭狀漏斗

MariaDB 與 Docker Compose 的 depends_on

/ 閱讀時間 4 分鐘

我先講結論:Docker Compose 的 depends_on 只能控制容器的執行順序,開完一個容器就會開下一個,不會等到容器正常執行才開下一個容器。導致單純使用 depends_on 時,就好像蒙面走鋼索。假設 B 容器相依於 A 容器提供的服務,要是 B 容器在 A 容器還沒執行正常時就開始,B 容器就無法正確初始化。

前幾天,我要用 Docker Compose 裝 Bookstack,使用 LinuxServer.io 的 image。如果使用範例的 docker-compose.yml,搭配他們家的 MariaDB image 可以正常運作,但是換成官方的 MariaDB image 卻無法正常運作。

看 log 有 connection refused 還以為是網路問題。花了一些時間才發現原因在於 MariaDB container 因為 bug 造成初始化時間很長。Bookstack container 在進行 php artisan migrate 時,資料庫尚未初始化完成,所以產生錯誤。

發現同樣是 MariaDB image,有些初始化時間長到造成錯誤,有些卻不會。所以做了一個實驗看看各個 MariaDB image 初始化需要的時間(以第一則到最後一則 log 的時間計算):

雖然在這邊只要用初始化時間短的 image 就沒問題,不過在其他狀況下,如何確保容器正常執行後,再開與它相依的容器呢?

  1. 放在不同的 docker-compose.yml,分別啓動
  2. healthcheck 搭配 depends_on
    • 可以參考這篇文章這篇文章
    • version 2.1 加入的選項,version 3 之後移除
    • 大概長這樣,bookstack 相依於 bookstack_db,不過 healthcheck 的檢定條件試不出來,下面這個是不能用的,只是示範:
version: "2.1"
services:
bookstack:
image: linuxserver/bookstack
container_name: bookstack
environment:
- PUID=1000
- PGID=1000
- DB_HOST=bookstack_db
- DB_USER=bookstack
- DB_PASS=yourdbpass
- DB_DATABASE=bookstackapp
restart: unless-stopped
depends_on:
bookstack_db:
condition: service_healthy
bookstack_db:
image: mariadb
container_name: bookstack_db
environment:
- MYSQL_ROOT_PASSWORD=yourdbpass
- MYSQL_DATABASE=bookstackapp
- MYSQL_USER=bookstack
- MYSQL_PASSWORD=yourdbpass
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 30s
timeout: 10s
retries: 10
restart: unless-stopped
  1. wait-for-it 之類的工具

覺得第一種方法比較省事,有需要再考慮第二種跟第三種。

好,講結論。使用 Docker Compose 時,如果有 docker container 要在另一個 docker container 完成初始化、正常執行後才啓動的話,不能只依賴 depends_on 選項,必須要用其他方式才能確保這些服務都正常運作。