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