Help us understand the problem. What is going on with this article?

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

本記事は、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 を追記して試します。
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"]

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

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 上書き

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"]

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

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 上書き?

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 の併用について

引数なし

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 が引数として実行されています。

引数あり

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 が実行されます。

残作業

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした