Dockerfile 的 CMD 和 ENTRYPOINT 区别与联系

一、CMD 和 ENTRYPOINT 使用方法

CMD 命令的三种用法:

The CMD instruction has three forms:
 
# exec 形式,这是首选形式,即官方推荐
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
# 作为 ENTRYPOINT 的参数
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
# shell 形式
CMD command param1 param2 (shell form)

ENTRYPOINT 命令的两种用法:

ENTRYPOINT has two forms:
# exec 形式,这是首选形式,即官方推荐
ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)
# shell 形式
ENTRYPOINT command param1 param2 (shell form)

二、示例

1、CMD 和 ENTRYPOINT 都可以作为容器启动的运行的命令。

容器启动运行 CMD 命令

Dockerfile:

FROM alpine
CMD ["/bin/sh", "-c", "echo 'hello cmd'"] # 等价于 CMD echo "hello cmd"

制作镜像:

[root@localhost test]# docker build -t hausen1012/test .
# 构建过程....

启动容器:

[root@localhost test]# docker run hausen1012/test
hello cmd
容器启动运行 ENTRYPOINT 命令

Dockerfile:

FROM alpine
ENTRYPOINT ["/bin/sh", "-c", "echo 'hello entrypoint'"] # 等价于 ENTRYPOINT echo "hello entrypoint" 

制作镜像:

[root@localhost test]# docker build -t hausen1012/test2 .
# 构建过程....

启动容器:

[root@localhost test]# docker run hausen1012/test2
hello entrypoint

结果:都能作为容器启动执行的命令。

2、多个 CMD 和 ENTRYPOINT 命令最后一条才生效

多个 CMD 命令

Dockerfile:

FROM alpine
CMD echo 111
CMD echo 222
CMD echo 333

制作镜像:

[root@localhost test]# docker build -t hausen1012/test3 .
# 构建过程....

启动容器:

[root@localhost test]# docker run hausen1012/test3
333
容器启动运行 ENTRYPOINT 命令

Dockerfile:

FROM alpine
ENTRYPOINT echo 111
ENTRYPOINT echo 222
ENTRYPOINT echo 333

制作镜像:

[root@localhost test]# docker build -t hausen1012/test4 .
# 构建过程....

启动容器:

[root@localhost test]# docker run hausen1012/test4
333

结果:同时写多个 CMD 或 ENTRYPOINT 只有最后一条生效


上面都是一样的,两个命令没有任何区别。下面讲讲区别。

3、Docker run 覆盖启动命令

容器启动时尝试覆盖 CMD 命令

Dockerfile:

FROM alpine
CMD ["/bin/sh", "-c", "echo 'hello cmd'"]

制作镜像:

[root@localhost test]# docker build -t hausen1012/test5 .
# 构建过程....

启动容器:

[root@localhost test]# docker run hausen1012/test5 echo "changed by run"
changed by run

可以看见本该输出 hello cmd,变成了 changed by run。

容器启动运行 ENTRYPOINT 命令

Dockerfile:

FROM alpine
ENTRYPOINT ["/bin/sh", "-c", "echo 'hello entrypoint'"]

制作镜像:

[root@localhost test]# docker build -t hausen1012/test6 .
# 构建过程....

启动容器:

[root@localhost test]# docker run hausen1012/test6 echo "changed by run"
hello entrypoint

可以看见,还是原来的输出。

结果:CMD 执行的启动命令可以被 Docker run 覆盖,但是 ENTRYPOINT 则不行。

4、CMD 作为 ENTRYPOINT 的参数

Dockerfile:

FROM alpine
CMD ["I am cmd"]
ENTRYPOINT ["echo"]

制作镜像:

[root@localhost test]# docker build -t hausen1012/test7 .
# 构建过程....

启动容器:

[root@localhost test]# docker run hausen1012/test7
I am cmd
[root@localhost test]# docker run hausen1012/test7 "I am run"
I am run

结果:CMD 可以作为 ENTRYPOINT 的参数,当 Docker run 传递参数时,会覆盖掉 CMD 的参数。

多个 CMD 传参时,只有最后一个 CMD 有效。

注意:

alpine 镜像里面没有 bash,即:
使用 CMD ["/bin/bash", “-c”, “echo ‘hello cmd’”] 会报错,
使用 CMD ["/bin/sh", “-c”, “echo ‘hello cmd’”] 则能正常输出。

上一篇:Dockerfile详解


下一篇:docker十一:docker-DockerFile案例-CMD、ENTRYPOINT、ONBUILD