はじめに
七尾百合子さん、お誕生日 276日目 おめでとうございます! nikkieです。
Dockerfile についての Today(※最近) I Learned です。
目次
- はじめに
- 目次
- Dockerfile reference 「Shell and exec form」
- 実はどちらの form でも書けたのです
- 2つの form は何が違うのか?ENTRYPOINTを例に
- 違いを分かってなかった私はやらかしていた
- 終わりに
Dockerfile reference 「Shell and exec form」
https://docs.docker.com/reference/dockerfile/#shell-and-exec-form
The
RUN,CMD, andENTRYPOINTinstructions all have two possible forms:
Dockerfile のRUN・CMD・ENTRYPOINT命令には2つの形式があります。
1つは exec form
https://docs.docker.com/reference/dockerfile/#exec-form
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]
もう1つは shell form
https://docs.docker.com/reference/dockerfile/#shell-form
RUN source $HOME/.bashrc && echo $HOME
ENTRYPOINT命令やRUN命令は form が違うだけということを認識できていませんでした。
実はどちらの form でも書けたのです
各命令はどちらの form でも書けます。
RUN
https://docs.docker.com/reference/dockerfile/#run
# Shell form: RUN [OPTIONS] <command> ... # Exec form: RUN [OPTIONS] [ "<command>", ... ]
shell form の方ではヒアドキュメントがサポートされています(&&つなぎからの解放!)
Dockerfilleで&&でつなげていたRUNコマンド、BuildKit有効にするとheredocsが書ける!https://t.co/LksLPPHKPy さらにRUN python3+heredocsでPythonのプログラムが書けちゃう👀 / “Introduction to heredocs in Dockerfiles - Docker Blog” https://t.co/j5sBecatCb
— nikkie(にっきー) / にっP (@ftnext) 2021年7月31日
CMD
https://docs.docker.com/reference/dockerfile/#cmd
# Shell form: CMD command param1 param2 # Exec form: CMD ["executable","param1","param2"] # Exec form, as default parameters to ENTRYPOINT CMD ["param1","param2"]
ENTRYPOINT
https://docs.docker.com/reference/dockerfile/#entrypoint
# Shell form: ENTRYPOINT command param1 param2 # Exec form: ENTRYPOINT ["executable", "param1", "param2"]
2つの form は何が違うのか?ENTRYPOINTを例に
shell form
https://docs.docker.com/reference/dockerfile/#entrypoint
It(*The shell form of
ENTRYPOINT) also starts yourENTRYPOINTas a subcommand of/bin/sh -c, which does not pass signals.
ENTRYPOINT command param1 param2は/bin/sh -c "command param1 param2"と実行されるということです。
このとき command にシグナルは渡されません。
別の説明としては1
https://docs.docker.com/reference/dockerfile/#shell-form-entrypoint-example
You can specify a plain string for the
ENTRYPOINTand it will execute in/bin/sh -c
exec form
https://docs.docker.com/reference/dockerfile/#exec-form-entrypoint-example
executable がコンテナで唯一のプロセスになります。
The following Dockerfile shows using the
ENTRYPOINTto run Apache in the foreground (i.e., asPID 1):
違いを分かってなかった私はやらかしていた
2つの form について Dockerfile のリファレンスは読み切れてはいないのですが、過去に書いた Dockerfile を変えたいなと思いました。
書き換えたい箇所
CMD ["python", "main.py"]
こうしたい
ENTRYPOINT ["python", "main.py"]
(リファレンスを読んだ範囲でCMD ["python", "main.py"]で PID 1 になるかが分からなかったので、ENTRYPOINTにしたいです)
また別で以下のようにしていた箇所があり、リファレンスを読んだ今ではこれは完全にあちゃーでした。
CMD ["/bin/sh", "-c", "python main.py"]
これではpythonコマンドにシグナルが渡りません!
ENTRYPOINTでやっていたら実に残念なことになってましたね
終わりに
Dockerfile に exec form と shell form があることを知りました。
RUN・CMD・ENTRYPOINT命令はそれぞれ、exec form と shell form の2通りで書けるENTRYPOINT命令 + exec form で、PID 1 のプロセスとなるENTRYPOINT命令 + shell form は/bin/sh -cで実行される。そのためシグナルが渡されない
過去に私が書いた際は生成 AI に書かせたのかもしれませんが、Dockerfile の知識がなくて墓穴を掘っていることに気づけていませんでした。
ENTRYPOINT命令 + exec form なのに /bin/sh -c を使用することは実質 shell formであり、exec formのよさを消す大悪手だと思います。
俺みたいになるな!
-
execコマンドを使った例になっています↩