Docker のオフィシャル・イメージから CMD と ENTRYPOINT の使い分け学ぶ
Dockerhub に掲載されているオフィシャル・イメージから、CMD と ENTRYOINT がどのように使われているか学びましょう。
オフィシャル・イメージの Dockerfile を見て構築方法を理解したい!
こちらのリンクをクリックして、さらに各オフィシャル・イメージのページに飛び、 そこに下の画像のようにDockerfile links
とか書かれているセクションがあれば、リンク先の Dockerfile に飛べます。
(以下は画像です、クリックできません。)
本記事の内容がわかりづらい場合、「コピペで学ぶチュートリアル: Dockerfile の CMD と ENTRYPOINT の違い」に沿って、自分でコピペしながら CMD と ENTRYPOINT の動作確認をすると、わかりやすくなるかもしれません。その後でも本記事がわかりづらければ、私の責任です。ごめんなさい。
nginx
docker pull nginx
docker inspect nginx
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"Entrypoint": [
"/docker-entrypoint.sh"
],
CMD はデフォルト引数だけではなく、nginx
コマンド自体も指定している CMD ["executable", "param1", "param2"…]
という形式なので、Docker 公式ドキュメントの Best practices for writing Dockerfilesに従っています。
The
CMD
instruction should be used to run the software contained in your image, along with any arguments.CMD
should almost always be used in the form ofCMD ["executable", "param1", "param2"…]
.
ENTRYPOINT はdocker-entrypoint.shというシェルスクリプトであり、nginx を実行する前の configuration を行っているようです。docker run
に追加の引数を何も与えなければ、ENTRYPOINT と CMD の組み合わせにより /docker-entrypoint.sh nginx -g daemon off;
というコマンドが実行され、configuration の後に nginx が立ち上がります。
httpd
docker pull httpd
docker inspect httpd
"Cmd": [
"httpd-foreground"
],
"Entrypoint": null,
CMD はhttpd-foreground
コマンド自体を指定している CMD ["executable", "param1", "param2"…]
という形式なので、Docker 公式ドキュメントの Best practices for writing Dockerfilesに従っています。
The
CMD
instruction should be used to run the software contained in your image, along with any arguments.CMD
should almost always be used in the form ofCMD ["executable", "param1", "param2"…]
.
そして ENTRYPOINT は null です。こちらもBest practicesのとおり、「イメージのユーザーが ENTRYPOINT の仕様を熟知していると期待できない場合、CMD ["param", "param"]
と ENTRYPOINT の組み合わせを使わない」に従っていると従っていると言えます。
CMD
should rarely be used in the manner ofCMD ["param", "param"]
in conjunction with ENTRYPOINT, unless you and your expected users are already quite familiar with how ENTRYPOINT works.
python
docker pull python
docker inspect python
"Cmd": [
"python3"
],
"Entrypoint": null,
CMD はインタラクティブなシェルを立ち上げるpython3
コマンドなので、Docker 公式ドキュメントの Best practices for writing Dockerfilesに従っています。
In most other cases, CMD should be given an interactive shell, such as bash, python and perl. For example,
CMD ["perl", "-de0"]
,CMD ["python"]
, orCMD ["php", "-a"]
.
ENTRYPOINT は null です。こちらもBest practicesのとおり、「イメージのユーザーが ENTRYPOINT の仕様を熟知していると期待できない場合、CMD ["param", "param"]
と ENTRYPOINT の組み合わせを使わない」に従っていると従っていると言えます。
CMD
should rarely be used in the manner ofCMD ["param", "param"]
in conjunction with ENTRYPOINT, unless you and your expected users are already quite familiar with how ENTRYPOINT works.
golang
docker pull golang
docker inspect golang
"Cmd": [
"bash"
],
"Entrypoint": null,
ENTRYPOINT は null です。
興味深いことに、golang のイメージは何も引数を与えずにdocker run golang
すると、CMD に指定されたbash
を実行して、即時終了します。Go のインタラクティブなシェルは立ち上げません。先程の Python のイメージとは流儀が異なっています。Go でインタラクティブなシェルを使うにはgo
コマンドではなく、 https://github.com/x-motemen/gore のようなツールを使うからでしょうか?
golang イメージ自体を直接docker run golang
する想定ではなく、下記のようにベースイメージとして golang を使い、ビルドコンテナとしてgo build
を行った後、CMD(もしくは ENTRYPOINT)を指定することを前提としていると考えると良さそうです。
FROM golang
...
RUN go build -o /some-exec-path
CMD ["/some-exec-path", "param1", "param2"]
golang イメージを使った Go のビルド方法は、公式ドキュメントの Build your Go image ページに説明があります。
openjdk
docker pull openjdk
docker inspect openjdk
"Cmd": [
"jshell"
],
"Entrypoint": null,
ENTRYPOINT は null です。
CMD はインタラクティブなシェルを立ち上げるjshell
コマンドなので、Docker 公式ドキュメントの Best practices for writing Dockerfilesに従っています。
In most other cases, CMD should be given an interactive shell, such as bash, python and perl. For example,
CMD ["perl", "-de0"]
,CMD ["python"]
, orCMD ["php", "-a"]
.
docker run --rm oepnjdk
INFO: Created user preferences directory.
| Welcome to JShell -- Version 18.0.2.1
| For an introduction type: /help intro
jshell> %
openjdk イメージは Java のビルドに使えますが、先程の golang とは違って CMD の形式になっているのが興味深いですね。
gradle
docker pull gradle
docker inspect gradle
"Cmd": [
"gradle"
],
"Entrypoint": null,
CMD はgradle
コマンド自体を指定している CMD ["executable", "param1", "param2"…]
という形式なので、Docker 公式ドキュメントの Best practices for writing Dockerfilesに従っています。
The
CMD
instruction should be used to run the software contained in your image, along with any arguments.CMD
should almost always be used in the form ofCMD ["executable", "param1", "param2"…]
.
gradle
コマンドはビルドを実行すると終了するので、インタラクティブなシェルを立ち上げるコマンドではありません。
golang, openjdk, gradle と、Dockerfile のFROM
で指定するベースイメージとして、ソースコードをビルドする際に使えるオフィシャル・イメージを見てきましたが、CMD の指定については三者三様ですね。
ubuntu
docker pull ubuntu
docker inspect ubuntu
"Cmd": [
"bash"
],
"Entrypoint": null,
Dockerfile のFROM
で指定するベースイメージとしての利用が一番多いと思われるので、CMD としてbash
のみが指定されています。イメージを使うユーザーが CMD や ENTRYPOINT を上書きすることが前提と考えてよいでしょう。
centos
docker pull centos
docker inspect centos
"Cmd": [
"/bin/bash"
],
"Entrypoint": null,
ubuntu 同様、Dockerfile のFROM
で指定するベースイメージとしての利用が一番多いと思われるので、CMD としてbash
のみが指定されています。イメージを使うユーザーが CMD や ENTRYPOINT を上書きすることが前提と考えてよいでしょう。
mysql
docker pull mysql
docker inspect mysql
"Cmd": [
"mysqld"
],
"Entrypoint": [
"docker-entrypoint.sh"
],
CMD はデフォルト引数だけではなく、mysqld
コマンド自体を指定している CMD ["executable", "param1", "param2"…]
という形式なので、Docker 公式ドキュメントの Best practices for writing Dockerfilesに従っています。
The
CMD
instruction should be used to run the software contained in your image, along with any arguments.CMD
should almost always be used in the form ofCMD ["executable", "param1", "param2"…]
.
ENTRYPOINT はdocker-entrypoint.shというシェルスクリプトであり、内容が難しくてよくわからなかったのですが… mysqld
を実行する前の事前準備を行っているのでは?と私は思っています。docker run
に追加の引数を何も与えなければ、ENTRYPOINT と CMD の組み合わせにより docker-entrypoint.sh mysqld
というコマンドが実行され、docker-entrypoint.sh
(による事前準備と思われる処理)の後にmysqld
が立ち上がります。
postgres
docker pull postgres
docker inspect postgres
"Cmd": [
"postgres"
],
"Entrypoint": [
"docker-entrypoint.sh"
],
CMD はデフォルト引数だけではなく、postgres
コマンド自体を指定している CMD ["executable", "param1", "param2"…]
という形式なので、Docker 公式ドキュメントの Best practices for writing Dockerfilesに従っています。
The
CMD
instruction should be used to run the software contained in your image, along with any arguments.CMD
should almost always be used in the form ofCMD ["executable", "param1", "param2"…]
.
ENTRYPOINT はdocker-entrypoint.shというシェルスクリプトであり、内容が難しくてよくわからなかったのですが… postgres
を実行する前の事前準備を行っているのでは?と私は思っています。docker run
に追加の引数を何も与えなければ、ENTRYPOINT と CMD の組み合わせにより docker-entrypoint.sh postgres
というコマンドが実行され、docker-entrypoint.sh
(による事前準備と思われる処理)の後にpostgres
サーバーが立ち上がります。
memcached
docker pull memcached
docker inspect memcached
"Cmd": [
"memcached"
],
"Entrypoint": [
"docker-entrypoint.sh"
],
CMD はデフォルト引数だけではなく、memcached
コマンド自体を指定している CMD ["executable", "param1", "param2"…]
という形式なので、Docker 公式ドキュメントの Best practices for writing Dockerfilesに従っています。
The
CMD
instruction should be used to run the software contained in your image, along with any arguments.CMD
should almost always be used in the form ofCMD ["executable", "param1", "param2"…]
.
ENTRYPOINT はdocker-entrypoint.shというほぼ何もしていない?シェルスクリプトで、与えられたコマンドを実行するのみのようです。docker run
に追加の引数を何も与えなければ、ENTRYPOINT と CMD の組み合わせにより docker-entrypoint.sh memcached
というコマンドが実行され、memcached
サーバーが立ち上がります。
wordpress
docker pull wordpress
docker inspect wordpress
"Cmd": [
"apache2-foreground"
],
"Entrypoint": [
"docker-entrypoint.sh"
],
CMD はデフォルト引数だけではなく、apache2-foreground
コマンド自体を指定している CMD ["executable", "param1", "param2"…]
という形式なので、Docker 公式ドキュメントの Best practices for writing Dockerfilesに従っています。
The
CMD
instruction should be used to run the software contained in your image, along with any arguments.CMD
should almost always be used in the form ofCMD ["executable", "param1", "param2"…]
.
ENTRYPOINT はdocker-entrypoint.shというシェルスクリプトで、おそらくは WordPress 立ち上げに必要は PHP の設定などを行っていると私は思っています。docker run
に追加の引数を何も与えなければ、ENTRYPOINT と CMD の組み合わせにより docker-entrypoint.sh apache2-foreground
というコマンドが実行され、apache2-foreground
サーバーが立ち上がります。
Discussion