Docker Composeの起動順序を確保する

Docker Composeを利用すると異種コンテナの設定をまとめて記述してdocker-compose upできて便利です。

ただし、Docker Composeの起動制御は想像しているものと違う可能性があり、注意が必要です。

設定ファイルのdepends_onディレクティブで起動順序を指定できるのですが、単に順番に起動アクションに入るだけで、前提サービスの起動完了を確認していません。
Controlling startup order in Compose

そのため、起動に時間のかかるRDBMSに接続できず、アプリケーションサーバーが異常終了する、という現象が起こります。

前提サービスの起動確認にdockerize

前提サービスが起動したことを確認するツールとして dockerizeを使えます。

このツールは、TCPやHTTP接続を試行し、準備できるまで待機する機能を提供します。

pingのようなネットワーククライアントとして実装されており、起動待ち処理を実装したいアプリケーションサーバなどのコンテナイメージにインストールしておきます(ビルド時)。

dockerizeの使い方

以下のようなRuby on Rails起動コマンドをDocker Composeのcommandディレクティブに指定しているとします。

unicorn_rails -c config/unicorn.rb -E development

以下のように、dockerizeコマンドをシェルスクリプトの&&(直前のコマンド成功時に後続のコマンド実行)で接続すると、サービス起動前にdockerizeの前提サービス待ち処理を差し込めます。

dockerize -wait tcp://dbms_postgres_1:5432 -timeout 3m && unicorn_rails -c config/unicorn.rb -E development

この例では、PostgreSQLをターゲットとして、Docker Compose内部ネットワーク上にあるdbms_postgres_1というホストの5432ポートにTCP接続を試みます(タイムアウト3分)。

ログを観察すると、5432ポートが利用可能になるまで5秒おきにTCPのサービス状況を確認している様子がわかります。

また、実際にはPostgreSQLがTCP接続を受け付ける状態になってからアプリ層でサービス提供可能になるまで少しタイムラグがあるため、実運用の際には、sleep 10s &&を追加しています。

dockerize -wait tcp://dbms_postgres_1:5432 -timeout 3m && sleep 10s && unicorn_rails -c config/unicorn.rb -E development

まとめ

依存関係のあるフルスタック型のサービス環境を立ち上げるには、前提環境の起動を順次完結した方が安定して動作します。

dockerize導入前には、一部のサービスが一定時間後にクラッシュしていたため、動作していないコンテナを特定して再起動したうえでフロントのプロキシも再起動、といった手間がかかっていました。

kubernetes上でdockerコンテナを運用する場合は、Service機構でコンテナ間に安定したネットワーク構造が提供されるため、待っていればいずれサービスが出揃うのでアバウトな運用が可能です。

開発環境のようにdocker単体で環境構築する場合は、dockerizeを活用することで、サービス群単位でUP/DOWNを操作できるようになり便利です。

中馬崇尋
Chuma Takahiro