EC2上のDockerコンテナをECSで稼働させる時につまづいた話
今回は、EC2上で稼働させたコンテナをECSに切り替える際、かなりハマったのでその内容を記事にしてみました。
タスクが立ち上がらない
元々EC2上でDockerコンテナを動かしていたので、ハマることは無いだろうと高を括っていたら、何度やっても上手く立ち上がってくれませんでした。
コンテナでは、Apache+PHP-FPM+Supervisorを動かして、フレームワークはLaravelを入れていました。
立ち上がらなかった原因は、ElastiCacheに接続できず、ヘルスチェックに失敗している状態でした。
デバッグの旅
ElastiCacheのホストはSecretManagerに設定していて、EC2上のDockerコンテナの時は問題なく稼働していたので、ホストの設定ミスは有りえません。
そうなるとネットワーク周りかと考えて、セキュリティグループの設定やVPCが一致しているかなども確認しましたが、ここも問題なし。
全く原因が分からないので、設定や環境変数周りにデバッグを埋め込んで、原因調査を行いました。
ホストが取れたり取れなかったり・・・?
Laravelのconfigにデバッグを仕込んで稼働させたところ、ElastiCacheのホストが取れているログと空のログが混在して出力されて頭の中がハテナで埋まりました。
どうやら、タイミングや箇所によって、SecretManagerの値が取得できないことがあるようでした。
この時点で、アプリケーションの問題ではなく「プロセスごとの実行環境の差異」を疑うべきだと考えました。
プロセスごとに異なる環境変数スコープ
今回の構成では、ECSタスク上で起動したコンテナのPID 1はSupervisorであり、PHP-FPMはその子プロセスとして起動されています。
ECSのタスク定義で設定した環境変数は、コンテナ起動時のプロセス(PID 1)には渡されます。しかし、その子プロセスに対しては、設定次第で完全には引き継がれない場合があります。
特にSupervisorは、設定によって環境変数を上書き・制限する挙動があるため、意図せず環境変数が欠落するケースがあります。
その結果、以下のような状態が発生していました。
- コンテナ直下で実行される処理 → 環境変数を取得できる
- Supervisor配下(PHP-FPM経由)の処理 → 環境変数が取得できない
Laravelのログで値が取れたり取れなかったりしたのは、この実行経路の違いが原因でした。
解決方法
対処として、Supervisorの設定ファイル(www.conf)側でSecretManager用の環境変数を明示的に定義することで、子プロセスにも確実に引き継ぐようにしました。
[www]
...
env[AWS_SECRET_MANAGER_KEY]=$AWS_SECRET_MANAGER_KEY
env[secret_vars]=$secret_varsこの設定を追加することで、Supervisor配下のPHP-FPMプロセスからも安定して環境変数が参照できるようになり、ElastiCacheへの接続エラーも解消しました。
key名や値は各環境で異なると思うので、適宜修正してください。
まとめ
ECSでアプリケーションを動かす場合、「タスク定義で環境変数を設定するだけ」では不十分なケースがあります。
実際にアプリケーションが動作するプロセスまで、環境変数が正しく引き継がれているかを意識することが重要です。
特にSupervisorのようなプロセスマネージャを利用している場合は、environmentディレクティブの設定を確認することをおすすめします。