5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DockerfileとECSタスク定義の使い分けに関する一考察

Posted at

はじめに

お疲れ様です。矢儀 @yuki_ink です。

ECS、使ってますか??

ECSでコンテナを動かすにあたり、必ず用意しないといけないのが次の2つです。

  • Dockerfile ※ひいてはDockerイメージ
  • ECSタスク定義

DockerfileとECSタスク定義の目的や用途は以下の通りで、両者は相互補完の関係にあると思います。

項目 Dockerfile ECSタスク定義
主目的 イメージのビルド イメージの実行設定
定義内容 アプリケーション構築の手順 コンテナの実行パラメータ
再利用性 アプリ単位で共通のものを利用 環境ごとに分ける
機密情報の扱い そもそも含めないようにする Secrets ManagerやSSM Parameter Storeと連携して取得

問題提起

ここで問題となるのは「どちらでも設定できる項目はどうすればいいの?」ということです。

記事執筆時点で、以下の項目については、Dockerfileでもタスク定義でも、どちらでも宣言できるものになっています。

  • 環境変数(ENV)
  • ヘルスチェック(HEALTHCHECK)
  • エントリポイント・コマンド(ENTRYPOINT / CMD)

これらの項目について、どこで設定を定義すべきなのか考えていきます。

結論

固定化する設定はDockerfileで、環境ごとに柔軟に設定する項目はタスク定義で!!

前提として、Dockerfileの設定よりタスク定義の設定の方が優先されます。
また、Dockerfileを修正すると、再度ビルド・ECRへのpushが必要になりますが、タスク定義だけなら、マネジメントコンソールからすぐに修正可能です。

そうを考えると、固定化する設定はDockerfileで、環境ごとに柔軟に設定する項目はタスク定義で というのが原則になると思います。


上記の上で、実運用を考えると、以下の2つの考え方ができます。

  • とりあえずDockerfileにデフォルト値を書いておいて、必要に応じてタスク定義でも書けばヨシ
  • Dockerfileとタスク定義で、それぞれで定義する項目をきっちり線引きする(タスク定義によるデフォルト値上書きはしない)

どちらの考え方もアリだと思いますが、いずれにせよ組織内でのルールを決めておくことが大事です。
その検討の中で役に立てばいいなという情報と私なりの考察を、以下に残しておきます。

1. 環境変数(ENV)

定義場所 推奨度 理由
Dockerfile 環境ごとの切替ができない。(むしろ固定させたい値についてはDockerfileでもいいかも)
タスク定義 ○ 推奨 デプロイ時に本番・ステージング・開発(Prod/Stg/Devなど)を指定して、簡単にアプリの動作を切り替えることができる。Secrets Manager/SSMとの連携も可能。CI/CDパイプラインで変数を差し込める柔軟性あり。

秘密鍵やDB接続文字列などはDockerfileに書かず、タスク定義で設定するのが原則です。
Dockerfileの ENV は、開発・ビルド時の設定用、あるいはデフォルト値程度に使うという考えで良いと思います。

2. ヘルスチェック(HEALTHCHECK)

定義場所 推奨度 理由
Dockerfile イメージに一体化したヘルスチェックで、どこで動かしても共通。ローカル開発で有効だが、ECSのオーケストレーションとは無関係。
タスク定義 ○ 推奨 ECSのオーケストレーションと連動。間隔・リトライなど柔軟に変更可。

ECSのヘルスチェックを利用することで、ステータスが「UNHEALTHY」なタスクを停止し、自動で新しいものに置き換えることが可能になります。
せっかくECSを使うなら、こちらを利用したほうが良いでしょう。

AWSのブログでは、最初にDockerfile上の HEALTHCHECK でヘルスチェックコマンドの正しさを確認したあと、同じ設定をタスク定義に仕込むことが推奨されています。

コンテナインスタンスをローカルでテストして、コンテナのヘルスチェックに合格することを確認する
コンテナインスタンスを Amazon ECS にプロビジョニングする前に、期待どおりに動作することを確認します。Docker Docs のウェブサイトにある HEALTHCHECK を使用してコンテナをテストします。コンテナが Dockerfile のヘルスチェックに合格することを確認します。次に、タスク定義でヘルスチェックの設定を指定し、Amazon ECS コンテナエージェントがヘルスチェックを監視、レポートできるようにします。

注: Docker ヘルスチェックがコンテナイメージに埋め込まれているがコンテナ定義で指定されていない場合、Amazon ECS ではモニタリングされません。コンテナ定義で指定されているヘルスチェックのパラメータは、コンテナイメージ内に存在する Docker ヘルスチェックを上書きします。

(出典)Amazon ECS タスクがコンテナヘルスチェックに合格できない場合に、トラブルシューティングする方法を教えてください。

3. エントリポイント・コマンド(ENTRYPOINT / CMD)

用途 定義場所
ENTRYPOINT コンテナ起動時に必ず実行すべきコマンド 変更されにくい処理のため、Dockerfileでの定義を推奨。処理をシェルスクリプトとしてまとめて、Dockerfileと一緒にバージョン管理するのが良い。
CMD デフォルトの引数またはコマンド(ENTRYPOINTの引数として使うことが多い) 変更が少なければDockerfile、変更が多ければECSタスク定義で。とりあえずデフォルト値をDockerfileに仕込むのも◎

繰り返しになりますが、固定化する設定はDockerfileで、環境ごとに柔軟に設定する項目はタスク定義で という原則に照らし合わせて考えていただければと思います。

以下、一例を示します。

  • ENTRYPOINT はアプリケーション本体の実行など、変更されることがない処理(例: ENTRYPOINT ["python", "app.py"])として設定。
  • CMD はデフォルト引数や動作モード(例: CMD ["--serve"])として設定。
ENTRYPOINT ["python", "app.py"]
CMD ["--serve"]

ECSタスク定義側で CMD を ["--debug"] にオーバーライドして、一時的なトラブルシューティングなどに利用することも可能です。

終わりに

以上、DockerfileとECSタスク定義の使い分けについて考えてみました。

「各種設定がどこで、どのように定義されているか」のルールが明確だと、トラブル時の調査・再現性・チーム内の認識合わせがとてもスムーズになります。
この記事を参考に、皆さんの組織で最適なルールを検討していただければ幸いです。

ここに記載した内容は私個人の意見なので、他にご意見があれば、積極的にコメントいただけますと幸いです!
よろしくお願いいたします!

参考にさせていただいた記事

参考にさせていただきました。
ありがとうございました。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?