DockerfileでENTRYPOINT、CMDを指定した時のベースイメージの挙動はどう変わるか

Docker

はじめに

先日投稿した以下のエントリは、今回のエントリを投稿するための前提知識になっています。

前提知識を整理しておきたかったためにまとめたものになっています。

僕らが Dockerfile を記述するときには、一行目に FROM というコマンドを記述します。
これは、Dockerイメージを作成する際に利用する ベースイメージ を指定するための命令となります。

ベースイメージも Dockerfile からビルドされたDockerイメージであり、 ENTRYPOINTCMD コマンドが Dcokerfile 内に記述されている場合があるわけです。

自分で作成するDockerfileに ENTRYPOINTCMD コマンドを記述した場合、それらはベースイメージの ENTRYOPTIONCMD とどう連携して動作するのでしょうか?

実験してみたいと思います。

検証環境

$ uname -moi
x86_64 MacBookPro16,1 Darwin

$ docker --version
Docker version 19.03.13, build 4484c46d9d

実験の流れ

  1. ENTRYPOINTCMD コマンドをそれぞれ設定した Dockerfile を作成・ビルドし、作成されたDockerイメージを実行してみる
  2. (1)で作成したDockerイメージを「ベースイメージ」とした Dockerfile を作成・ビルドし、作成されたDockerイメージを実行してみる。作成するDockerfileは以下の4つのパターンとする
    • ENTRYPOINTCMD の両方を設定しない
    • ENTRYPOINTCMD の両方を設定する
    • ENTRYPOINT だけ設定する
    • CMD だけ設定する

親となるDockerfileの作成・ビルド・実行

まずは となるDockerfileを作成します。

# cat <<EOF >Dockerfile
FROM bash

ENTRYPOINT ["echo"]

CMD ["2", "5"]
EOF

ビルドします。( イメージ名は parent という名前で作成します。 )

$ docker build -t parent .

実行します。

$ docker run parent
2 5

ENTRYPOINTCMD の挙動の仕組みがまだ把握できていない場合は、以下のエントリを読んで頂くことをおすすめします。

子となるDockerfileの作成・ビルド・実行

先程作成したばかりのベースイメージとなるDockerイメージを使って、新たなDockerイメージを作り、実行させてみます。
新たなDockerfileは4つのパターンのものを作成してみます。

1. ENTRYPOINT、CMD の両方を設定しない

Dockerfileを作成・ビルド・実行します。

※ベースイメージには先程作成したDockerイメージを利用します。 (イメージ名は parent でしたね。)

# 作成
$ cat <<EOF >Dockerfile
FROM parent
EOF

# ビルド
$ docker build -t child1 .

# 実行
$ docker run child1
2 5

ENTRYPOINT、CMD の両方を設定しない場合は、ベースイメージの設定がそのまま利用されます。

2. ENTRYPOINT、CMD の両方を設定する

Dockerfileを作成・ビルド・実行します。

※ベースイメージには先程作成したDockerイメージを利用します。

# 作成
$ cat <<EOF >Dockerfile
FROM parent

ENTRYPOINT ["seq"]

CMD ["3", "4"]
EOF

# ビルド
$ docker build -t child2 .

# 実行
$ docker run child2
3
4

ENTRYPOINT、CMDを設定する場合は、ベースイメージの設定が上書きされます。

3. ENTRYPOINT だけ設定する

Dockerfileを作成・ビルド・実行します。

※ベースイメージには先程作成したDockerイメージを利用します。

# 作成
$ cat <<EOF >Dockerfile
FROM parent

ENTRYPOINT ["seq"]
EOF

# ビルド
$ docker build -t child3 .

# 実行
$ docker run child3
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

少々分かりにくいですが、これは seq コマンドを引数無しで実行した結果となっています。

ENTRYPOINT だけを設定する場合は、ベースイメージの設定が上書きされると同時に、 CMD 設定がクリアされ、 ENTRYPOINT だけが設定されている状態となります。

4. CMD だけ設定する

Dockerfileを作成・ビルド・実行します。

※ベースイメージには先程作成したDockerイメージを利用します。

# 作成
$ cat <<EOF >Dockerfile
FROM parent

CMD ["7", "10"]
EOF

# ビルド
$ docker build -t child4 .

# 実行
$ docker run child4
7 10

CMD だけを設定する場合は、ベースイメージの CMD 設定が上書きされますが、 ENTRYPOINT の設定はそのまま引き継がれます。

ひとこと

この挙動をどう有効活用するのがベストプラクティスなのかは深く理解できておらず。

Docker