Docker
dockerfile
DockerDay 6

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

More than 3 years have passed since last update.

本記事は、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