我先講結論: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 的時間計算):
- mariadb:4 分 09 秒
- mariadb/server:3 分 54 秒
- bitnami/mariadb:10 秒
- linuxserver/mariadb:12 秒
- demyx/mariadb:看不出來,應該也是很短
雖然在這邊只要用初始化時間短的 image 就沒問題,不過在其他狀況下,如何確保容器正常執行後,再開與它相依的容器呢?
- 放在不同的
docker-compose.yml
,分別啓動 - 用
healthcheck
搭配depends_on
- 用
wait-for-it
之類的工具
覺得第一種方法比較省事,有需要再考慮第二種跟第三種。
好,講結論。使用 Docker Compose 時,如果有 docker container 要在另一個 docker container 完成初始化、正常執行後才啓動的話,不能只依賴 depends_on
選項,必須要用其他方式才能確保這些服務都正常運作。