はじめに
ECSで起動タイプFargateのタスクを実行する際の「コマンドの上書き」という項目について、「実行時パラメータを渡せるようなものかな」と思って使おうとしました。
この理解でざっくり正解と言えますが、正しく使うにはdockerのENTRYPOINT、CMDコマンドの知識が必要で、自分のようにdockerを使いこなす前にFargateを使おうとした人にとってはハマりどころかと思います。
これらについて調べた内容を記載しています。
コマンドの上書き
ECSタスクの実行やタスクスケジュールの設定画面で「コンテナの上書き」という項目があり、ここで設定した内容をECSタスクに設定したコンテナ実行時に利用することができます。
「コンテナの上書き」の中に「コマンドの上書き」というフリー記述項目があります。
画面上のヒントメッセージに「コンテナに渡す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
[コマンドの上書きなし]
[コマンドの上書きあり]
[結果]
・コマンド上書きありなしどちらでも、arg is ENTRYPOINTが必ず出力されている
→ENTRYPOINTは必ず実行される
・コマンドの上書きを設定した場合、arg is override1, arg is override2が出力されている
→ENTRYPOINTにパラメータを渡すCMDとして処理される
CMD
[コマンドの上書きなし]
[コマンドの上書きあり]
[結果]
・arg is CMDはコマンド上書き時に出力されない
→コンテナ定義のCMDは無視され、コマンドの上書きの内容がCMDとして処理される
両方設定したもの
[コマンドの上書きなし]
[コマンドの上書きあり]
[結果]
・test_script.shのecho処理が実行されている
→ENTRYPOINTは必ず実行される
・arg is BOTHはコマンド上書き時に出力されない
→コンテナ定義のCMDは無視され、コマンドの上書きの内容がCMDとして処理される
調査結果
[こちら](#### 実行時(docker run時)のパラメータ)で述べたように、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/