LoginSignup
58
29

More than 3 years have passed since last update.

【AWS ECS】Fargateの「コマンドの上書き」

Posted at

はじめに

ECSで起動タイプFargateのタスクを実行する際の「コマンドの上書き」という項目について、「実行時パラメータを渡せるようなものかな」と思って使おうとしました。
この理解でざっくり正解と言えますが、正しく使うにはdockerのENTRYPOINT、CMDコマンドの知識が必要で、自分のようにdockerを使いこなす前にFargateを使おうとした人にとってはハマりどころかと思います。
これらについて調べた内容を記載しています。

コマンドの上書き

ECSタスクの実行やタスクスケジュールの設定画面で「コンテナの上書き」という項目があり、ここで設定した内容をECSタスクに設定したコンテナ実行時に利用することができます。
00_container_override.png
「コンテナの上書き」の中に「コマンドの上書き」というフリー記述項目があります。
画面上のヒントメッセージに「コンテナに渡すCMD」とありますが、どういうことか次項で説明します。

dockerのENTRYPOINTとCMD

dockerfileで「ENTRYPOINT」と「CMD」という命令があり、どちらもコンテナ実行時(docker run時)に実行されるコマンドです。
「コマンドの上書き」の挙動を理解するためにこれらの理解が必要となります。

この2つは、コンテナ実行時に渡されるパラメータの扱いが異なります。
ENTRYPOINTはdocker runのパラメータをそのままENTRYPOINTのパラメータとして扱います。
CMDはdocker runのパラメータをCMD自体として扱います。(CMDの上書き)

ENTRYPOINT

コンテナ実行時に必ず実行されるコマンドと引数(省略可)を設定します。
[書式]

ENTRYPOINT ["実行可能なもの", "パラメータ1", "パラメータ2"]

[例]

ENTRYPOINT ["ping", "localhost"]
→pingコマンドにlocalhostという引数を渡して実行

CMD

コンテナ実行時のデフォルト実行コマンドと引数を設定します。
[書式]

CMD ["実行バイナリ", "パラメータ1", "パラメータ2"]

[例]

CMD ["ping", "localhost"]
→pingコマンドにlocalhostという引数を渡して実行

併用

ENTRYPOINTとCMDを併用する場合、CMDにはENTRYPOINTに渡すパラメータを設定します。
[書式]

ENTRYPOINT ["実行可能なもの", "パラメータ1", "パラメータ2"]
CMD ["パラメータ3", "パラメータ4"]

[例]
以下の2例はどちらも同じコマンドが実行される

ENTRYPOINT [“ping”]
CMD[“-c”,”4”,“localhost”]
→ping -c 4 localhost になる
ENTRYPOINT [“ping”,”-c”]
CMD[”4”,“localhost”]
→ping -c 4 localhost になる

実行時(docker run時)のパラメータ

docker run実行時に指定したパラメータはコンテナ定義のCMDとしてコンテナに渡され、コンテナ起動時にはこのCMDが採用されます。(CMDの上書き)
前項の「コマンドの上書き」はこの仕様に相当します

[書式]

docker run <コンテナ指定> パラメータ1 パラメータ2

[例]
コンテナ定義に「ENTRYPOINT [“ping”,”localhost”]」の設定がある場合、ENTRYPOINT + CMDの併用となる

docker run <コンテナ> -c 4
→ping localhost -c 4 になる

コンテナ定義に「CMD [“ping”,”localhost”]」の設定がある場合、CMDを上書きとなる

docker run <コンテナ> echo hoge
→pingは実行されず、echo hogeが実行される

コンテナ定義に「ENTRYPOINT [“ping”,”localhost”]」と「CMD [“-c”,”4”]」の設定がある場合、CMDを上書きとなる

docker run <コンテナ> -c 10
→ping localhost -c 10 になる

動作確認

前項での実行時パラメータの仕様通りに動くか、「コマンドの上書き」の動作確認をします。
ENTRYPOINTを設定したもの、CMDを設定したもの、両方設定したもの、の3つのコンテナ定義を作成し、それぞれコマンドの上書きなし・ありで実行した場合の系6パターンの出力を確認します。

テスト用ファイル

test_script.shを作成。シェルに渡された引数をechoする。

#!/bin/sh

# 引数の数をecho
echo arg length is $#

# 渡された引数を全てecho
for x
do
  echo arg is "$x"
done

コンテナ定義

[ENTRYPOINTを設定したもの]

FROM ubuntu
COPY . .
RUN chmod 777 test_script.sh

ENTRYPOINT ["sh", "test_script.sh", "ENTRYPOINT"]

[CMDを設定したもの]

FROM ubuntu
COPY . .
RUN chmod 777 test_script.sh

CMD ["sh", "test_script.sh", "CMD"]

[両方設定したもの]

FROM ubuntu
COPY . .
RUN chmod 777 test_script.sh

ENTRYPOINT ["sh", "test_script.sh"]
CMD ["BOTH"]

テスト実行

ENTRYPOINT

[コマンドの上書きなし]
03_entrypoint_1.png
[コマンドの上書きあり]
03_entrypoint_2.png
03_entrypoint_3.png
[結果]
・コマンド上書きありなしどちらでも、arg is ENTRYPOINTが必ず出力されている
 →ENTRYPOINTは必ず実行される
・コマンドの上書きを設定した場合、arg is override1, arg is override2が出力されている
 →ENTRYPOINTにパラメータを渡すCMDとして処理される

CMD

[コマンドの上書きなし]
04_cmd_1.png
[コマンドの上書きあり]
04_cmd_2.png
04_cmd_3.png
[結果]
・arg is CMDはコマンド上書き時に出力されない
 →コンテナ定義のCMDは無視され、コマンドの上書きの内容がCMDとして処理される

両方設定したもの

[コマンドの上書きなし]
05_both_1.png
[コマンドの上書きあり]
05_both_2.png
05_both_3.png
[結果]
・test_script.shのecho処理が実行されている
 →ENTRYPOINTは必ず実行される
・arg is BOTHはコマンド上書き時に出力されない
 →コンテナ定義のCMDは無視され、コマンドの上書きの内容がCMDとして処理される

調査結果

こちらで述べたように、Fargateの「コマンドの上書き」はコンテナ実行時にCMDとして渡されるものでした。
コンソールでの「コンテナに渡すCMD」というヒントメッセージがそのまま正解ですね。

所感としては、「コマンド」というワードがここではdockerの用語の「CMD」を表しているようで、自分はこの点が少しわかりにくさを感じました。
(英語表記でも「Command」のようです)
使うのにdocker知識が前提に感じるので、どうせなら「CMDの上書き」の方がわかりやすい気がします。

注意点

ECSの開発者ガイドで、コンテナ定義にENTRYPOINTがある場合とない場合の「コマンドの上書き」の設定について記載されていますが、誤解しそうな表現になっていると思います。
[ENTRYPOINTがない場合の説明]

If your container definition does not specify an ENTRYPOINT, the format should be a comma-separated list of non-quoted strings. For example:
/bin/sh,-c,echo,$DATE

[ENTRYPOINTがある場合の説明]

If your container definition does specify an ENTRYPOINT (such as sh,-c), the format should be an unquoted string, which is surrounded with double quotes and passed as an argument to the ENTRYPOINT command. For example:
while true; do echo $DATE > /var/www/html/index.html; sleep 1; done

「ENTRYPOINTがない場合はカンマ区切り」という点と、ENTRYPOINTがある場合のサンプルから、「ENTRYPOINTがある場合はカンマ区切り指定ではない」と自分には見えましたが、動作確認で実証したようにENTRYPOINTがあってもカンマ区切り指定可能でした。

参考

ECSの開発者ガイド
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs_run_task_fargate.html

Dockerfile リファレンス
http://docs.docker.jp/v1.11/engine/reference/builder.html

ENTRYPOINTは「必ず実行」、CMDは「(デフォルトの)引数」
https://pocketstudio.net/2020/01/31/cmd-and-entrypoint/

58
29
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
58
29