はじめに
ローカル環境のFlowをdocker composeで動かしている際、アプリとDBのコンテナが同時に立ち上がることに気が付きました。
自己満足でありますが、依存関係を綺麗にしようとおもい、depends_onとhelthcheckという機能を使ってみたので、備忘として残します。
経緯
以前書いた記事で、Flowをdocker composeで動かすためのdocker-compose.ymlを書きました。
services:
app:
build:
context: .
dockerfile: ./Docker/php/Dockerfile
ports:
- "8082:8081"
db:
image: mysql:8.0.36
volumes:
- db_data3:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mydatabase
ports:
- "3306:3306"
volumes:
db_data3: {}
動作確認的には問題なく動いているのですが、起動ログを見ると、アプリとDBのコンテナが同時に立ち上がっています。
> docker compose up
[+] Running 1/1r Desktop o View Config w Enable Watch
✔ Container quickstart-db-1 Recreated 0.1s
Attaching to app-1, db-1
db-1 | 2025-12-28 04:54:50+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.36-1.el8 started.
app-1 | rm: cannot remove '/app/Packages/Application/Added.Package': Is a directory
app-1 | rm: cannot remove '/app/Packages/Application/Neos.Welcome': Is a directory
app-1 | rm: cannot remove '/app/Packages/Application/Test.Package': Is a directory
app-1 | rm: cannot remove '/app/Packages/Application/Tomita.Test': Is a directory
app-1 | rm: cannot remove '/app/Packages/Application/Tomita.Test2': Is a directory
db-1 | 2025-12-28 04:54:50+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
db-1 | 2025-12-28 04:54:50+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.36-1.el8 started.
db-1 | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
db-1 | 2025-12-28T04:54:50.692897Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
db-1 | 2025-12-28T04:54:50.694191Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.36) starting as process 1
db-1 | 2025-12-28T04:54:50.701526Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
db-1 | 2025-12-28T04:54:50.858890Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
db-1 | 2025-12-28T04:54:51.075629Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
db-1 | 2025-12-28T04:54:51.075675Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
db-1 | 2025-12-28T04:54:51.081432Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
db-1 | 2025-12-28T04:54:51.120271Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
db-1 | 2025-12-28T04:54:51.120522Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
app-1 | Executed a database schema update.
app-1 | Server running. Please go to http://0.0.0.0:8081 to browse the application.
app-1 | [Sun Dec 28 04:54:53 2025] PHP 8.2.29 Development Server (http://0.0.0.0:8081) started
アプリ側のエントリーポイントshellスクリプトでやっていることが多いおかげで問題にはなっていませんが、アプリはDBに依存しているので、これはちょっと気持ち悪いです。
DBが準備できてからアプリ側を立ち上げるよう変更してみましょう。
そこで、docker composeのdepends_onとhealthcheckという機能を使い、コンテナ同士の依存関係を定義しようと思います。
depends_onとhelthcheck
depends_onはコンテナの依存関係を示すためのオプションです。
アプリ側のdepends_onにDBのコンテナを指定することで、アプリはDBに依存しているとみなし、DBの準備完了までコンテナの立ち上げを待つようになります。
helthcheckは、立ち上げたコンテナのヘルスチェックに利用するコマンドを示すためのオプションです。
この二つを組み合わせることで、アプリ側はDB側がhealthyになるまでコンテナの立ち上げをしないように制御することが可能です。
services:
app:
build:
context: .
dockerfile: ./Docker/php/Dockerfile
ports:
- "8082:8081"
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.0.36
volumes:
- db_data3:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mydatabase
ports:
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db_data3: {}
アプリ側では、depends_onの対象にdbを追加し、依存関係を明示しました。
conditionは、依存先がどんな状態になったら立ち上げ始めるかを定義できます。
-
service_started:コンテナが立ち上がり始めたら -
service_healthy:コンテナが立ち上がり、ヘルスチェックが通ったら -
service_completed_successfully:コンテナが正常終了したら
今回はDB側の準備が終わったらアプリ側を立ち上げたかったので、service_healthyにしました。
DB側ではhealthcheckを追加し、その際のコマンドと、実行間隔、タイムアウト、リトライ回数を定義しました。
これにより、DBのコンテナの準備ができた後に、アプリケーションサーバを立ち上げることができました。
> docker compose up
[+] Running 1/1
✔ Container quickstart-db-1 Recreated 0.1s
Attaching to app-1, db-1
db-1 | 2025-12-28 07:41:52+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.36-1.el8 started.
db-1 | 2025-12-28 07:41:52+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
db-1 | 2025-12-28 07:41:52+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.36-1.el8 started.
db-1 | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
db-1 | 2025-12-28T07:41:52.746291Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
db-1 | 2025-12-28T07:41:52.747658Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.36) starting as process 1
db-1 | 2025-12-28T07:41:52.754175Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
db-1 | 2025-12-28T07:41:52.921542Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
db-1 | 2025-12-28T07:41:53.087987Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
db-1 | 2025-12-28T07:41:53.088026Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
db-1 | 2025-12-28T07:41:53.090659Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
db-1 | 2025-12-28T07:41:53.133088Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
db-1 | 2025-12-28T07:41:53.133443Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
app-1 | rm: cannot remove '/app/Packages/Application/Added.Package': Is a directory
app-1 | rm: cannot remove '/app/Packages/Application/Neos.Welcome': Is a directory
app-1 | rm: cannot remove '/app/Packages/Application/Test.Package': Is a directory
app-1 | rm: cannot remove '/app/Packages/Application/Tomita.Test': Is a directory
app-1 | rm: cannot remove '/app/Packages/Application/Tomita.Test2': Is a directory
app-1 | Executed a database schema update.
app-1 | Server running. Please go to http://0.0.0.0:8081 to browse the application.
app-1 | [Sun Dec 28 07:42:06 2025] PHP 8.2.29 Development Server (http://0.0.0.0:8081) started
ちなみに、依存先のコンテナがhealthyにならない場合、以下のようなエラーが出力されます。
dependency failed to start: container quickstart-db-1 is unhealthy
おわりに
今回はdocker composeのdepends_onとhealthcheckを利用し、コンテナ同士の依存関係を定義してみました。
自分はあくまでローカルで使用するだけなのでそこまでメリットはないですが、本番等で利用する場合は必須の機能ですね。
また、実行順序を制御できるこの機能はコンテナの数が多くなった場合に大きなメリットをもたらしそうです。
ここまでご覧いただきありがとうございました!