DockerfileでENTRYPOINT、CMDの挙動を動かしながら理解する
はじめに
Dockerfile内で指定可能なコマンドはいくつかありますが、 ENTRYPOINT コマンドと CMD コマンドは初見ではわかりくいコマンドとなっています。
この2つのコマンドが、Dockerコンテナの実行にどのように影響するか、実行させながら理解していきたいと思います。
検証環境
$ uname -moi
x86_64 MacBookPro16,1 Darwin
$ docker --version
Docker version 19.03.13-beta2, build ff3fbc9d55
Dockerイメージ実行時の実行コマンドの組み立てロジック
今回は結論から入ります。
Dockerイメージ内で実行されるコマンド は、以下の3つの要素を使って組み立てられます。
- Dockerfile内の ENTRYPOINTの設定値
docker run IMAGE_NAME
コマンド実行時の コマンドライン引数- Dockerfile内の CMDの設定値
2と3の両方が設定されている場合は、 2が優先され、3は無視 されます。
結果、 Dockerイメージ内で実行されるコマンド は以下のようになります。
<ENTRYPOINTの設定値> <コマンドライン引数|CMDの設定値>
具体的な例を見ていきたいと思います。
Dockerfileに ENTRYPOINT と CMD の両方が指定されている場合
ENTRYPOINT と CMD の両方が指定されたDockerfileから、Dockerイメージを作成してみます。
# Dockerfileを作成
$ cat <<'EOF' >Dockerfile
FROM alpine:3.11.3
ENTRYPOINT ["seq"]
CMD ["1", "5"]
EOF
# my_docker_image_01 という名前のDockerイメージを作成
$ docker build -t my_docker_image_01 .
Dockerイメージを実行 (コマンドライン引数なし)
まずは作成されたDockerイメージを、イメージ名の後方に引数をつけずに実行してみます。
$ docker run my_docker_image_01
1
2
3
4
5
<ENTRYPOINTの設定値> <コマンドライン引数|CMDの設定値>
という実行コマンド組み立てルールから、 seq 1 5
が実行されています。
Dockerイメージを実行 (コマンドライン引数あり)
今度はイメージ名の後方に引数を付与して実行してみます。
$ docker run my_docker_image_01 2 4
2
3
4
<ENTRYPOINTの設定値> <コマンドライン引数|CMDの設定値>
という実行コマンド組み立てルールから、 seq 2 4
が実行されています。
コマンドライン引数 のほうが優先され、 CMDの設定値 は無視されました。
Dockerfileに ENTRYPOINT だけが指定されている場合
ENTRYPOINT だけが指定されたDockerfileから、Dockerイメージを作成してみます。
# Dockerfileを作成
$ cat <<'EOF' >Dockerfile
FROM alpine:3.11.3
ENTRYPOINT ["seq"]
EOF
# my_docker_image_02 という名前のDockerイメージを作成
$ docker build -t my_docker_image_02 .
Dockerイメージを実行 (コマンドライン引数なし)
$ docker run my_docker_image_02
BusyBox v1.31.1 () multi-call binary.
Usage: seq [-w] [-s SEP] [FIRST [INC]] LAST
Print numbers from FIRST to LAST, in steps of INC.
FIRST, INC default to 1.
-w Pad to last with leading zeros
-s SEP String separator
<ENTRYPOINTの設定値> <コマンドライン引数|CMDの設定値>
という実行コマンド組み立てルールから、 seq
が引数無しで実行されます。
seqコマンドは引数が必須のため、エラーが発生したというわけです。
Dockerイメージを実行 (コマンドライン引数あり)
今度はイメージ名の後方に引数を付与して実行してみます。
$ docker run my_docker_image_02 2 3
2
3
<ENTRYPOINTの設定値> <コマンドライン引数|CMDの設定値>
という実行コマンド組み立てルールから、 seq 2 3
が実行されています。
Dockerfileに CMD だけが指定されている場合
CMD だけが指定されたDockerfileから、Dockerイメージを作成してみます。
ただし、今回は先程のCMDの設定とは異なる値としています。
# Dockerfileを作成
$ cat <<'EOF' >Dockerfile
FROM alpine:3.11.3
CMD ["seq", "1", "5"]
EOF
# my_docker_image_03 という名前のDockerイメージを作成
$ docker build -t my_docker_image_03 .
Dockerイメージを実行 (コマンドライン引数なし)
$ docker run my_docker_image_03
1
2
3
4
5
<ENTRYPOINTの設定値> <コマンドライン引数|CMDの設定値>
という実行コマンド組み立てルールから、 seq 1 5
が実行されています。
ENTRYPOINTの設定値 が空なので、 CMDの設定値 だけで実行コマンドが組み立てられました。
Dockerイメージを実行 (コマンドライン引数あり)
コマンドライン引数を付与して実行してみますが、こちらも先程までと少し異なっている点に注意しましょう。( seq
の文字が含まれています。 )
$ docker run my_docker_image_03 seq 2 3
2
3
<ENTRYPOINTの設定値> <コマンドライン引数|CMDの設定値>
という実行コマンド組み立てルールから、 seq 2 3
が実行されています。
やはり ENTRYPOINTの設定値 が空なので、 コマンドライン引数 だけで実行コマンドが組み立てられました。
ひとこと
この仕組みは、 Docker Compose や Kubernetes の設定時にも理解しておく必要があります。
ディスカッション
コメント一覧
まだ、コメントがありません