1. Dockerfile里指定执行命令用RUN、ENTRYPOING和CMD有何不同?

  • RUN仅仅是在 docker build 时运行的。
  • docker build完成之后会打包成一个镜像,只有执行docker run后,才会执行CMD或者ENTRYPOINT。
  • ENTRYPOINT和CMD的不同点在于执行docker run时参数传递方式。

区别如下:

1.1 CMD指定的命令可以被docker run传递的命令覆盖。

1.1.1 Dockerfile仅仅使用CMD指令

Dockerfile:

FROM ubuntu
CMD ["echo", "far"]
➜  docker build -t run-test:0.1 .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM ubuntu
 ---> 93fd78260bd1
Step 2/2 : CMD ["echo", "far"]
 ---> Running in 0f97a65b839e
Removing intermediate container 0f97a65b839e
 ---> 22e6e82769ea
Successfully built 22e6e82769ea
Successfully tagged run-test:0.1

>>> 我们可以看到,构建过程中并没有执行CMD中的echo指令,只是看到了构建信息 <<<
➜  docker run run-test:0.1
far
>>> 我们可以看到,在执行docker run后,CMD中的echo命令被执行了 <<<
➜  docker run run-test:0.1 echo bor
bor

>>> 我们可以看到,在执行docker run后,CMD中的echo命令被docke run的命令参数覆盖了。 <<<

1.1.2 Dockerfile即使用CMD又使用RUN

Dockerfile:

FROM ubuntu
CMD ["echo", "far"]
RUN ["echo", "foo"]
➜  docker build -t run-test:0.1 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM ubuntu
 ---> 93fd78260bd1
Step 2/3 : CMD ["echo", "far"]
 ---> Running in 44ef2a9c88ca
Removing intermediate container 44ef2a9c88ca
 ---> 559ca9f008a5
Step 3/3 : RUN ["echo", "foo"]
 ---> Running in f801910112ab
foo
Removing intermediate container f801910112ab
 ---> 6d042893d5e9
Successfully built 6d042893d5e9
Successfully tagged run-test:0.1

>>> 我们可以看到,构建过程中并没有执行CMD的echo指令,但是执行了RUN指令 <<<
➜  docker run run-test:0.1
far

>>> 我们可以看到,在执行docker run后,CMD中的echo命令被执行了 <<<
➜  docker run run-test:0.1 echo bor
bor

>>> 我们可以看到,在执行docker run后,CMD中的echo命令被docke run的命令参数覆盖了。 <<<

1.2 ENTRYPOINT会把容器名后面的所有内容都当成参数传递给其指定的命令

1.1.1 Dockerfile仅仅使用ENTRYPOINT指令

Dockerfile:

FROM ubuntu
ENTRYPOINT ["echo", "far"]
➜  docker build -t run-test:0.1 .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM ubuntu
 ---> 93fd78260bd1
Step 2/2 : ENTRYPOINT ["echo", "far"]
 ---> Running in ede61562f973
Removing intermediate container ede61562f973
 ---> 76dd760e3382
Successfully built 76dd760e3382
Successfully tagged run-test:0.1

>>> 我们可以看到,构建过程中并没有执行echo指令,只是看到了构建信息 <<<
➜  docker run run-test:0.1
far

>>> 我们可以看到,在执行docker run后,ENTRYPOINT中的echo命令被执行了 <<<
➜  docker run run-test:0.1 echo bor
far echo bor

>>> 我们可以看到,在执行docker run后,ENTRYPOINT会把容器名后面的所有内容都当成参数传递给其指定的命令 <<<
>>> 2. 另外,我们可以发现,在Dockerfile中,ENTRYPOINT指定的参数比运行docker run时指定的参数更靠前。
       例如此处实际上是执行了:echo "far echo bor"

1.1.2 Dockerfile即使用ENTRYPOINT又使用RUN

Dockerfile:

FROM ubuntu
ENTRYPOINT ["echo", "far"]
RUN ["echo", "foo"]
➜  docker build -t run-test:0.1 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM ubuntu
 ---> 93fd78260bd1
Step 2/3 : ENTRYPOINT ["echo", "far"]
 ---> Running in b0e86020ab3e
Removing intermediate container b0e86020ab3e
 ---> 5d389a86c0dc
Step 3/3 : RUN ["echo", "foo"]
 ---> Running in f4eb7745c7a3
foo
Removing intermediate container f4eb7745c7a3
 ---> 323ab1e07c2e
Successfully built 323ab1e07c2e
Successfully tagged run-test:0.1

>>> 我们可以看到,构建过程中并没有执行ENTRYPOINT的echo指令,但是执行了RUN指令 <<<
➜  docker run run-test:0.1
far

>>> 我们可以看到,在执行docker run后,ENTRYPOINT中的echo命令被执行了 <<<
➜  docker run run-test:0.1 echo bor
far echo bor

>>> 1. 我们可以看到,在执行docker run后,ENTRYPOINT会把容器名后面的所有内容都当成参数传递给其指定的命令。 <<<
>>> 2. 另外,我们可以发现,在Dockerfile中,ENTRYPOINT指定的参数比运行docker run时指定的参数更靠前。
       例如此处实际上是执行了:echo "far echo bor"