[docker] CMD とENTRYPOINT の違いを試してみた

  • 92
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

本記事は、Docker Advent Calendar 2015 の12月6日の記事になります。

概要

Dockerfile にCMDENTRYPOINT ってあるけどなにが違うのか調査とそのメモ

環境

  • OS : cent7.1
cat /etc/redhat-release
  # CentOS Linux release 7.1.1503 (Core)
  • docker : 1.9.0
[root@docker-engine /]# docker version
  # Client:
  #  Version:      1.9.0
  #  API version:  1.21
  #  Go version:   go1.4.2
  #  Git commit:   76d6bc9
  #  Built:        Tue Nov  3 18:00:05 UTC 2015
  #  OS/Arch:      linux/amd64

  # Server:
  #  Version:      1.9.0
  #  API version:  1.21
  #  Go version:   go1.4.2
  #  Git commit:   76d6bc9
  #  Built:        Tue Nov  3 18:00:05 UTC 2015
  #  OS/Arch:      linux/amd64

※ install はこちらを参照

Dockerfile

  • 今回の主なDockerfile はこちらになります。 これにCMDENTRYPOINT を追記して試します。
Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

CMDENTRYPOINT

  • docker image からdocker container を実行するときにCMDENTRYPOINT の記述内容が実行されます。
  • 1つのDockerfile にCMDENTRYPOINT は1度のみ。
    ※ 複数記載されている場合、最後の1個が実行される。

agenda

  • CMD について
    • CMD ["command"]
    • CMD command
    • CMD 上書き
  • ENTRYPOINT について
    • ENTRYPOINT ["command"]
    • ENTRYPOINT command
    • ENTRYPOINT 上書き?
  • CMD とENTRYPOINT の併用について

CMD

CMD ["command"]

Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

CMD ["ping","127.0.0.1","-c","100"]

build

[root@localhost ~]# docker build -t test .
  # Sending build context to Docker daemon 37.89 kB
  # Step 1 : FROM ubuntu
  #  ---> e9ae3c220b23
  # Step 2 : MAINTAINER hihihiroro
  #  ---> Using cache
  #  ---> 5b349e87daf9
  # Step 3 : CMD ping 127.0.0.1 -c 100
  #  ---> Running in 401e07b7dca7
  #  ---> 0ac2c0ea0e28
  # Removing intermediate container 401e07b7dca7
  # Successfully built 0ac2c0ea0e28

run

[root@localhost ~]# docker run test
  # PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
  # 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.033 ms
  # 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.040 ms
  # 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.034 ms
  # ...

プロセス確認

root@0b2a435c091b:/# ps auxf
  # USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
  # root         6  0.6  0.0  18136  1864 ?        Ss   06:00   0:00 /bin/bash
  # root        19  0.0  0.0  15560  1104 ?        R+   06:00   0:00  \_ ps auxf
  # root         1  0.2  0.0   6500   612 ?        Ss   06:00   0:00 ping 127.0.0.1 -c 100

ping が実行されていることが分かります。
シェルを介さずに実行されていることが分かります。

CMD command

Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

CMD ping 127.0.0.1 -c 100

build

[root@localhost ~]# docker build -t test .
  # Sending build context to Docker daemon 37.89 kB
  # Step 1 : FROM ubuntu
  #  ---> e9ae3c220b23
  # Step 2 : MAINTAINER hihihiroro
  #  ---> Running in 7d6a1adc76ee
  #  ---> 03615a451ecf
  # Removing intermediate container 7d6a1adc76ee
  # Step 3 : CMD ping 127.0.0.1 -c 100
  #  ---> Running in c304f24111ab
  #  ---> dea31bd0fe0f
  # Removing intermediate container c304f24111ab
  # Successfully built dea31bd0fe0f

run

[root@localhost ~]# docker run test
  # PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
  # 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.033 ms
  # 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.040 ms
  # 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.034 ms
  # ...

プロセス確認

root@b86ea4cdcd54:/# ps auxf
  # USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
  # root         7  0.4  0.0  18136  1860 ?        Ss   06:04   0:00 /bin/bash
  # root        20  0.0  0.0  15560  1100 ?        R+   06:04   0:00  \_ ps auxf
  # root         1  0.2  0.0   4440   628 ?        Ss   06:04   0:00 /bin/sh -c ping 127.0.0.1 -c 100
  # root         6  0.0  0.0   6500   624 ?        S    06:04   0:00 ping 127.0.0.1 -c 100

ping が実行されていることが分かります。
/bin/sh -c の引数としてコマンドが実行されていることが分かります。

CMD 上書き

Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

CMD ping 127.0.0.1 -c 100

build

[root@localhost ~]# docker build -t test .
  # Sending build context to Docker daemon 37.89 kB
  # Step 1 : FROM ubuntu
  #  ---> e9ae3c220b23
  # Step 2 : MAINTAINER hihihiroro
  #  ---> Running in 7d6a1adc76ee
  #  ---> 03615a451ecf
  # Removing intermediate container 7d6a1adc76ee
  # Step 3 : CMD ping 127.0.0.1 -c 100
  #  ---> Running in c304f24111ab
  #  ---> dea31bd0fe0f
  # Removing intermediate container c304f24111ab
  # Successfully built dea31bd0fe0f

run

[root@localhost ~]# docker run test cat /etc/lsb-release
  # DISTRIB_ID=Ubuntu
  # DISTRIB_RELEASE=14.04
  # DISTRIB_CODENAME=trusty
  # DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"

ping ではなく、docker run 時につけた引数のcat /etc/lsb-release が実行されていることが分かります。
CMD はこのように、docker run 時にコマンドの上書きが可能になります。

ENTRYPOINT

ENTRYPOINT ["command"]

Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

ENTRYPOINT ["ping","127.0.0.1","-c","100"]

build

[root@localhost ~]# docker build -t test .
  # Sending build context to Docker daemon 37.89 kB
  # Step 1 : FROM ubuntu
  #  ---> e9ae3c220b23
  # Step 2 : MAINTAINER hihihiroro
  #  ---> Running in 4bd4f60f6a50
  #  ---> 2ffc6e2fdd8a
  # Removing intermediate container 4bd4f60f6a50
  # Step 3 : ENTRYPOINT ping 127.0.0.1 -c 100
  #  ---> Running in 173206d72cb6
  #  ---> e5b47e6740cd
  # Removing intermediate container 173206d72cb6
  # Successfully built e5b47e6740cd

run

[root@localhost ~]# docker run test
  # PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
  # 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.025 ms
  # 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.034 ms
  # 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.029 ms
  # ...

プロセス確認

root@124425f5edd0:/# ps auxf
  # USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
  # root         6  0.4  0.0  18136  1864 ?        Ss   06:33   0:00 /bin/bash
  # root        19  0.0  0.0  15560  1104 ?        R+   06:33   0:00  \_ ps auxf
  # root         1  0.1  0.0   6500   604 ?        Ss   06:33   0:00 ping 127.0.0.1 -c 100

ping が実行されていることが分かります。
シェルを介さずに実行されていることが分かります。

ENTRYPOINT command

Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

ENTRYPOINT ping 127.0.0.1 -c 100

build

[root@localhost ~]# docker build -t test .
  # Sending build context to Docker daemon 37.89 kB
  # Step 1 : FROM ubuntu
  #  ---> e9ae3c220b23
  # Step 2 : MAINTAINER hihihiroro
  #  ---> Running in 8679d9b8120c
  #  ---> bdc1d6d8e004
  # Removing intermediate container 8679d9b8120c
  # Step 3 : ENTRYPOINT ping 127.0.0.1 -c 100
  #  ---> Running in ec29024e6074
  #  ---> 3963c62c7464
  # Removing intermediate container ec29024e6074
  # Successfully built 3963c62c7464

run

[root@localhost ~]# docker run test
  # PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
  # 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.030 ms
  # 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.031 ms
  # 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.028 ms
  # ...

プロセス確認

root@7d8390b4e1f4:/# ps auxf
  # USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
  # root         7  1.0  0.0  18136  1856 ?        Ss   06:37   0:00 /bin/bash
  # root        20  0.0  0.0  15560  1104 ?        R+   06:37   0:00  \_ ps auxf
  # root         1  0.2  0.0   4440   632 ?        Ss   06:37   0:00 /bin/sh -c ping 127.0.0.1 -c 100
  # root         6  0.0  0.0   6500   632 ?        S    06:37   0:00 ping 127.0.0.1 -c 100

ping が実行されていることが分かります。
/bin/sh -c の引数としてコマンドが実行されていることが分かります。

ENTRYPOINT 上書き?

Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

ENTRYPOINT ping 127.0.0.1 -c 100

build

[root@localhost ~]# docker build -t test .
  # Sending build context to Docker daemon 37.89 kB
  # Step 1 : FROM ubuntu
  #  ---> e9ae3c220b23
  # Step 2 : MAINTAINER hihihiroro
  #  ---> Running in 2f72cd03c162
  #  ---> dd99c6e04b1a
  # Removing intermediate container 2f72cd03c162
  # Step 3 : ENTRYPOINT ping 127.0.0.1 -c 100
  #  ---> Running in 449d1f1b2280
  #  ---> 61277c329249
  # Removing intermediate container 449d1f1b2280
  # Successfully built 61277c329249

run

[root@localhost ~]# docker run test cat /etc/lsb-release
  # PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
  # 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.028 ms
  # 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.053 ms
  # 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.032 ms
  #  ...

CMD とは違い、docker run 時につけた引数のcat /etc/lsb-release ではなく、ENTRYPOINT で指定されているping が実行されていることが分かります。
ENTRYPOINTCMD と違い、docker run 時にコマンドの上書きができません。
docker run --entrypoint="" で上書きはすることが可能です。

CMD とENTRYPOINT の併用について

引数なし

Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

ENTRYPOINT ["ping"]
CMD ["127.0.0.1", "-c", "50"]

build

[root@localhost ~]# docker build -t test .
  # Sending build context to Docker daemon 39.42 kB
  # Step 1 : FROM ubuntu
  #  ---> e9ae3c220b23
  # Step 2 : MAINTAINER hihihiroro
  #  ---> Running in 33a067cc7f3e
  #  ---> 57ff677a0cca
  # Removing intermediate container 33a067cc7f3e
  # Step 3 : ENTRYPOINT ping
  #  ---> Running in 2957c1b4f09e
  #  ---> 3c30112fe595
  # Removing intermediate container 2957c1b4f09e
  # Step 4 : CMD 127.0.0.1 -c 50
  #  ---> Running in 09f1cff264bd
  #  ---> c7160151ed57
  # Removing intermediate container 09f1cff264bd
  # Successfully built c7160151ed57

run

[root@localhost ~]# docker run test
  # PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
  # 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.024 ms
  # 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.033 ms
  # 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.031 ms
  # ...

プロセス確認

root@23a769d5c382:/# ps auxf
  # USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
  # root         6  1.0  0.0  18136  1860 ?        Ss   07:16   0:00 /bin/bash
  # root        19  0.0  0.0  15560  1100 ?        R+   07:16   0:00  \_ ps auxf
  # root         1  0.2  0.0   6500   632 ?        Ss   07:16   0:00 ping 127.0.0.1 -c 50

ENTRYPOINT で指定したpingCMD で指定した127.0.0.1 -c 50 が引数として実行されています。

引数あり

Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

ENTRYPOINT ["ping"]
CMD ["127.0.0.1", "-c", "50"]

build

[root@localhost ~]# docker build -t test .
  # Sending build context to Docker daemon 39.42 kB
  # Step 1 : FROM ubuntu
  #  ---> e9ae3c220b23
  # Step 2 : MAINTAINER hihihiroro
  #  ---> Running in 33a067cc7f3e
  #  ---> 57ff677a0cca
  # Removing intermediate container 33a067cc7f3e
  # Step 3 : ENTRYPOINT ping
  #  ---> Running in 2957c1b4f09e
  #  ---> 3c30112fe595
  # Removing intermediate container 2957c1b4f09e
  # Step 4 : CMD 127.0.0.1 -c 50
  #  ---> Running in 09f1cff264bd
  #  ---> c7160151ed57
  # Removing intermediate container 09f1cff264bd
  # Successfully built c7160151ed57

run

[root@localhost ~]# docker run test localhost
  # PING localhost (127.0.0.1) 56(84) bytes of data.
  # 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.027 ms
  # 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.037 ms
  # 64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.029 ms
  # ...

プロセス確認

root@947cf9dfb3c1:/# ps auxf
  # USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
  # root         6  1.3  0.0  18136  1864 ?        Ss   07:26   0:00 /bin/bash
  # root        19  0.0  0.0  15560  1104 ?        R+   07:26   0:00  \_ ps auxf
  # root         1  0.3  0.0   8596   832 ?        Ss   07:26   0:00 ping localhost

ENTRYPOINT で指定したping に引数のlocalhostCMD で指定した127.0.0.1 -c 50 を上書きして実行しています。

まとめ

共通点

  • docker run 時に実行されるコマンドです。
  • docker run 時に引数を渡すとコマンドを上書きできます。 ※ENTRYPOINT--entrypoint オプションが必要です。

差分

  • CMDdocker run 時の引数でCMD commandCMD ["command"]command 分をまるっと上書きして実行されます。
  • ENTRYPOINTdocker run 時の引数がENTRYPOINT ["command"]command の引数として実行されます。

併用

  • ENTRYPOINTCMD の両方が書いてある場合には、CMD に書かれている内容が、ENTRYPOINT に書いてあるcommand のオプションとして実行されます。
  • docker run 時に引数をつけた場合、CMD の内容が上書きされENTRYPOINT に書いてあるcommand が実行されます。

残作業

Dockerfile
FROM ubuntu

MAINTAINER hihihiroro

ENTRYPOINT ping -c 50

build

[root@localhost ~]# docker build -t test .
  # Sending build context to Docker daemon 39.42 kB
  # Step 1 : FROM ubuntu
  #  ---> e9ae3c220b23
  # Step 2 : MAINTAINER hihihiroro
  #  ---> Running in 403dff6b0a29
  #  ---> a3be8411fe60
  # Removing intermediate container 403dff6b0a29
  # Step 3 : ENTRYPOINT ping -c 50
  #  ---> Running in 98beb40ba98d
  #  ---> f7d65704e8bc
  # Removing intermediate container 98beb40ba98d
  # Successfully built f7d65704e8bc

run

[root@localhost ~]# docker run test 127.0.0.1
  # Usage: ping [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
  #             [-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
  #             [-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
  #             [-w deadline] [-W timeout] [hop1 ...] destination
  • ENTRYPOINT ["command"] の際にはdocker run 時の引数をcommand の引数に付けて実行してくれるが、ENTRYPOINT command の際には引数を付けてくれない。

参考

Docker
Docker run reference
Dockerfile reference