dockerコンテナを実行可能ファイルとして扱う。
やりたいこと
docker run <IMAGE_NAME> params
で単一の処理を行いたいということです。docker hub
でよくある形式だと思います。サーバやCLIなどでよく見る実行方法ですね。
docker run
の後ろにpython ...
などを書くのは面倒なので、これを使ってみたいなと思った次第です。
自分の場合では、python
ファイルの実行を行いたいので、python
を使って実践してみることにしました。
すること
Dockerfile
でENTRYPOINT
とCMD
を使えばできます。実験ではpython
は引数の表示だけさせます。
ENTRYPOINTとCMDの両方を指定する
引数に何もしないときはヘルプメッセージを表示して、適切な引数を指定したときは適切な処理を行います。
Dockerfile
を次にようにします:
FROM python:alpine
COPY main.py /etc/src/main.py
WORKDIR /etc/src/
CMD [ "--help" ]
ENTRYPOINT [ "python", "main.py" ]
こうすることで、docker run --rm <IMAGE_NAME>
ではヘルプが表示されます。
main.py
は実験では以下のようなとてもシンプルなものです:
from sys import argv
print(argv);
実際はargparse
を使うので、--help
が渡れば対応したメッセージが表示されます。
何が起きているか
ENTRYPOINT
とCMD
が両方指定されているとき、CMD
はENTRYPOINT
の引数として機能します。そのためENTRYPOINT
で["python", "main.py"]
を指定して、CMD
で["--help"]
を指定しているわけです。
一方で、docker run --rm <IMAGE_NAME> tekisetsu
などで起動すれば、CMD
のヘルプの引数--help
は上書きされて、ENTRYPOINT
の引数にはtekisetsu
が渡されて期待通りの動作をします。
$ docker run --rm -it <image_name>
['main.py', '--help']
$ docker run --rm -it sugukesu tekisetsu
['main.py', 'tekisetsu']
このような出力になります。
片方だけ指定する場合
片方だけ設定した場合について調べたので、下に結果をまとめておきます。
CMDだけ指定するとき
CMD ["python", "main.py"]
だけ定義して、ENTRYPOINT
を定義しないとき、docker run
で引数を渡すとどうなるか調べました。
python
にはargv
だけ出力させました:
$ docker run --rm -it <image_name>
['main.py']
$ docker run --rm -it <image_name> foobar
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"foobar\": executable file not found in $PATH": unknown.
となり、docker run
で引数を与えると、CMD
を上書きすることがわかります。この場合では、存在しないファイルfoobar
を実行してエラーが発生しています。
ENTRYPOINTだけ指定するとき
今度はENTRYPOINT ["python", "main.py"]
だけを定義して、CMD
を定義しないとき、docker run
で引数を渡すとどうなるか調べました。
Dockerfile
とmain.py
は先ほどと同じものを利用しています。(CMD
をENTRYPOINT
に置換しただけです):
$ docker run --rm -it <image_name>
['main.py']
$ docker run --rm -it <image_name> foo
['main.py', 'foo']
$ docker run --rm -it <image_name> foo bar
['main.py', 'foo', 'bar']
$ docker run --rm -it <image_name> "foo bar"
['main.py', 'foo bar']
ENTRYPOINT
の後ろに引数が追加されていくことがわかります。
エントリポイントの名称の通りの動作だと実感できます。確実に実行されるexcutable
だということですね。
おわり
引数を["aa", "bb", ...]
のように指定するexec形式
と呼ばれる指定方法を前提にしていました。これが推奨されている記述方法であり、他の方法では/bin/bash -c
に渡されて起動したりするようなので、場合によっては想定外の動作をすると思います。
日本語化してあるドキュメントに助けられました: Dockerfile リファレンス — Docker-docs-ja 20.10 ドキュメント
実際に色々変えて動かしてみるって大事ですね。思ったよりENTRYPOINT
がエントリポイントになっていて、よくできているなと感じます。
以上です。
Amazonアソシエイト
コメント