バックエンドとフロントエンドが分かれていたり、細かいルーティングを行うWebアプリケーションではローカルの開発環境でnginxをプロキシサーバとしてかますことが多いと思います。
しかし、docker compose up
で立ち上げた初期はバックエンドのアプリケーションが起動中となりアクセスするとnginx側から502が返ってきてしまうことがよくあります*1。ローカル環境なので、開発体験の粋ではりますが、エンジニア以外がローカル環境を立ち上げた際に混乱のもとになりかねません。
この記事では、そのようなことが起こらないようにするためのdocker composeのhealthcheck
を使用したWebアプリケーションの起動チェックについて解説していきます。
healthcheck とは
docker compose v2.1 で追加された機能の一つでtest
で指定したコマンドを実行し成功したらhealty
となる機能です。depends_on
を使うことでhealty
になったら他のコンテナを起動するといったことができるようになります。
使い方
この記事では、docker composeでの使い方を解説します。DockerfileでもHEALTHCHECK
があるようですが、そちらの使い方は公式ドキュメントを参照してください。
まず、ヘルスチェックしたいコンテナに対して以下のように記述します。
healthcheck: test: "curl --fail http://localhost:8080 || exit 1" interval: 5s timeout: 30s retries: 5 start_period: 30s
test
- 実際にヘルスチェックで実行されるコマンドです。例ではcurlを使っていますが、alpineイメージだとデフォルトで入っていないので
RUN apk update && apk add --no-cache curl
をすると良さそうです。 - mysqlのヘルスチェックでは
mysqladmin ping
なども使えます
- 実際にヘルスチェックで実行されるコマンドです。例ではcurlを使っていますが、alpineイメージだとデフォルトで入っていないので
interval
- 前回のコマンドが0以外で終了した場合リトライをします。その間隔です。
- また、初回のコマンド実行前にもintervalの秒数待つようです。
timeout
- コマンド実行のタイムアウトです。
retries
- リトライ回数です。
start_period
- コンテナがスタートするまでの秒数です。パッケージのインストールなどで時間がかかることが予想される場合、この秒数を長くするといいかもしれません。
- このperiodの範囲内では
test
のコマンドが実行されますが、失敗してもリトライ回数にカウントされません。しかし、成功したらHealthy
となります。
その後、ヘルスチェック後に起動したいコンテナに対してdepends_on
を設定します。
depends_on: frontend: condition: service_healthy backend: condition: service_healthy
condition: service_healthy
とすることで依存元のコンテナがHealthy
になったタイミングで依存先のコンテナが立ち上がるようになります。
作成例
以下は、私の趣味で作っているプロダクトで実際に使っているcompose.yaml
です。GoのバックエンドサーバーとNext.jsのフロントエンドサーバーがあり、nginxを通って配信されています。
この例では、GoとNext.jsの両コンテナにヘルスチェックを追加してnginxではservice_healthy
でdepends_on
をしています。これにより、両方のバックエンドサーバーが起動完了してからnginxが立ち上がるので502が返ってくることがなくなります。
参考文献
- Compose file version 3 reference | Docker Docs
- docker-compose の depends_on と healthcheck について - アクトインディ開発者ブログ
- How To Successfully Implement A Healthcheck In Docker Compose
*1:特にNext.jsでApp Routerを使っている場合、ローカル環境立ち上げが遅いです。