对于Dockerfile的ENTRYPOINT和CMD命令,网上有很多教程,但是有些众口不一,这里验证几个问题。
是否必须要写?
-
编写一个Dockerfile,内容为:
FROM centos
-
执行命令
docker build . -t test:v1
。——发现能成功生成镜像。
结论:ENTRYPOINT、CMD命令可以不写,不妨碍构建镜像。
实际上,这里新生成的镜像与原镜像共用同一个Image ID,只是tag不同。
可以写几个?
-
编写一个Dockerfile,内容为:
FROM centos CMD ["1"] CMD ["2"] CMD ["3"] ENTRYPOINT ["echo", "4"] ENTRYPOINT ["echo", "5"] ENTRYPOINT ["echo", "6"]
-
构建镜像。
-
启动容器。——发现终端上显示“6 3”。
-
执行命令
docker ps -n 1 --no-trunc
。——发现该容器的启动命令COMMAND是"echo 6 3"
。
结论:ENTRYPOINT、CMD命令最多各写一个,否则只有最后一个会生效。并且,即使CMD命令写在ENTRYPOINT命令之前,最终依然会附加到ENTRYPOINT命令之后。
shell格式与exec格式有什么区别?
-
编写一个Dockerfile,内容为:
FROM centos ENTRYPOINT ["/bin/bash", "echo", "1"] CMD /bin/bash echo 2
-
构建镜像。
-
使用docker inspect命令查看该镜像的具体信息。——发现如下内容:
"Cmd": [ "/bin/sh", "-c", "/bin/bash echo 2" ], ... "Entrypoint": [ "/bin/bash", "echo", "1" ],
-
启动容器。
-
执行命令
docker ps -n 1 --no-trunc
。——发现容器的启动命令COMMAND是"/bin/bash echo 1 /bin/sh -c '/bin/bash echo 2'"
。
结论:Dockerfile中,shell格式的命令会被转换成exec格式再保存,并且转换时会加上前缀"/bin/sh"和"–c"。最终被容器执行时又会变回shell格式。
ENTRYPOINT与CMD命令怎么相互影响?
ENTRYPOINT命令有两种写法,CMD命令有三种写法。
- 参考教程:CMD和ENTRYPOINT的用法
这里列表统计不同写法时、一个ENTRYPOINT命令与一个CMD命令组合的结果(即最终的容器启动命令是什么)。
- | ENTRYPOINT echo 1 | ENTRYPOINT ["echo", "1"] |
---|---|---|
CMD echo 2 | /bin/sh -c ‘echo 1’ /bin/sh -c ‘echo 2’ | echo 1 /bin/sh -c ‘echo 2’ |
CMD ["echo", "2"] | /bin/sh -c ‘echo 1’ echo 2 | echo 1 echo 2 |
CMD ["2"] | /bin/sh -c ‘echo 1’ 2 | echo 1 2 |
结论:
CMD命令会直接附加到ENTRYPOINT命令之后,合并成容器的启动命令。
如果CMD命令是shell格式的,还会加上前缀"/bin/sh –c"。
当ENTRYPOINT命令采用shell格式时,不会被CMD命令影响,可以忽略CMD命令。