soranoba
soranoba Author of soranoba.net
programming

DockerfileのENTRYPOINTでシェル形式を使いつつ引数を渡す

事の発端は「DockerfileのENTRYPOINTENVの変数展開ができない!」でした。以下の指定は正しく動作しません。

ENTRYPOINT ["./$APP"]
CMD ["--level=0"]

そこで、下記の条件をどうにかして満たせないかと調べてみました。

  • ENTRYPOINTCMDを使い分ける
    • ENTRYPOINT: 実行バイナリパス
    • CMD: 実行バイナリに指定する引数 (docker run時に指定)
  • ENTRYPOINTENVの変数展開を行う
  • 推奨されているexec形式 (ENTRYPOINTで配列の形で指定する方法) を使用する

ENVの変数展開をする為にはシェルを使用する

シェル 形式とは異なり、 exec 形式はシェルを呼び出しません。つまり、通常のシェル上の処理はされません。例えば、 ENTRYPOINT [“echo”, “$HOME”] は $HOME を変数展開しません。シェル上の処理が必要であれば、 シェル 形式を使うか、シェルを直接実行します。例: ENTRYPOINT [ “sh”, “-c”, “echo”, “$HOME” ]。変数は Dockerfile で ENV を使って定義することができ、 Dockerfile パーサー上で展開されます。

Dockerfile リファレンス - ENTRYPOINT より

リファレンスにあるように、変数展開を行う為にはこの方法(ENTRYPOINT [ "sh", "-c", "echo", "$HOME" ])を使う必要があります。
しかし、この状態だとCMDで指定した引数がshコマンドの引数として渡されてしまいます。

実行バイナリに引数を渡す

-c string If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.

man shより

そこで、この仕様をうまく使ってみることにしました。

$ sh -c 'echo %@'

$ sh -c 'echo $@' 1 2 3
2 3
$ sh -c 'echo $@' '' 1 2 3
1 2 3

引数を指定しない場合にも対応する為に、$0を空文字列にし、それ以降を$@で取得することができそうです。

まとめ

ENTRYPOINT ["sh", "-c", "./$APP $@", ""]
CMD ["--level=0"]

とすることで、CMDで引数を渡すことができました。👏👏

(Updated: )

comments powered by Disqus