在写Dockerfile中需要指定容器启动时运行的命令,CMD和ENTRYPOINT都可以实现,但其实是有区别的。CMD是指定容器启动时默认运行命令,那么在没有ENTRYPOINT运行命令,就会执行CMD的运行命令,可能会被忽略。ENTRYPOINT指定容器启动时运行的命令,一定会执行。
1.CMD指定容器启动时默认运行命令
CMD格式
1)exec格式:CMD ["executable","param1","param1"] ;CMD的推荐格式
2)shell格式:CMD command param1 param2
如果docker run指定了其他命令,CMD指定的默认命令将会被忽略掉。
# cat Dockerfile
FROM almalinux
MAINTAINER luorf
CMD ["/bin/echo","CMD>>Hello World1","CMD>>Hello World2"]
# docker build -f ./Dockerfile -t cmdtest:V1 .
# docker image ls|grep cmdtest
cmdtest V1 30160a00abdb 16 months ago 198MB
说明:CMD的param1、param2连续执行
# docker run -it cmdtest:V1
CMD>>Hello World1 CMD>>Hello World2
[root@docker docker]#
说明:CMD的param1、param2都被/bin/bash覆盖忽略
# docker run -it cmdtest:V1 /bin/bash
[root@e0314b2b5af1 /]#
如果Dockerfile存在多个CMD指令,则只有最后一个CMD有效。
# cat Dockerfile
FROM almalinux
MAINTAINER luorf
CMD ["/bin/echo","CMD>>Hello World1"]
CMD ["/bin/echo","CMD>>Hello World2"]
# docker build -f ./Dockerfile -t cmdtest:V2 .
# docker image ls|grep cmdtest|grep V2
cmdtest
V2 28c7ebd0fc82 16 months ago 198MB
说明:多条CMD,仅执行最后一条CMD.
# docker run -it cmdtest:V2
CMD>>Hello World2
CMD命令解析变量
# cat Dockerfile
FROM almalinux
MAINTAINER luorf
CMD ["/bin/sh","-c","echo hello,$HOSTNAME"] # -c参数表示解析变量
# docker build -f ./Dockerfile -t cmdtest:V3 .
# docker image ls|grep cmdtest|grep V3
cmdtest V3 b98bc6808584 16 months ago 198MB
# docker run -it cmdtest:V3
hello,b667060b8c6a
2.ENTRYPOINT指定容器启动时运行的命令
ENTRYPOINT格式
1)exec格式:ENTRYPOINT ["executable","param1","param1"] ;ENTRYPOINT 推荐格式
2)shell格式:ENTRYPOINT command param1 param2
如果docker run指定了其他命令,ENTRYPOINT指定的命令不会被忽略。
# cat Dockerfile_ENTRYPOINT
FROM almalinux
MAINTAINER luorf
ENTRYPOINT ["/bin/echo","CMD>>Hello World1"]
# docker build -f ./Dockerfile_ENTRYPOINT -t entrypointtest:V1 .
# docker image ls|grep entrypointtest|grep V1
entrypointtest V1 f2812d2994ab 16 months ago 198MB
# docker run -it entrypointtest:V1
CMD>>Hello World1
说明:entrypoint的param1没有被/bin/bash覆盖忽略
# docker run -it entrypointtest:V1 /bin/bash
CMD>>Hello World1 /bin/bash
如果Dockerfile存在多个ENTRYPOINT 指令,则只有最后一个ENTRYPOINT 有效;
# cat Dockerfile_ENTRYPOINT
FROM almalinux
MAINTAINER luorf
ENTRYPOINT ["/bin/echo","CMD>>Hello World1"]
ENTRYPOINT ["/bin/echo","CMD>>Hello World2"]
# docker build -f ./Dockerfile_ENTRYPOINT -t entrypointtest:V2 .
# docker image ls|grep entrypointtest|grep V2
entrypointtest V2 2a46f5a1fde6 16 months ago 198MB
说明:多行ENTRYPOINT,仅最后一行有效
# docker run -it entrypointtest:V2
CMD>>Hello World2
ENTRYPOINT的exec格式用于设置要执行的命令和参数,同时可通过CMD提供额外的参数
# cat Dockerfile_ENTRYPOINT
FROM almalinux
MAINTAINER luorf
CMD ["/bin/echo","World"]
ENTRYPOINT ["/bin/echo","CMD>>Hello "]
# docker build -f ./Dockerfile_ENTRYPOINT -t entrypointtest:V3 .
# docker image ls|grep entrypointtest|grep V3
entrypointtest V3 f56e2b8394f4 16 months ago 198MB
说明:通过CMD提供了额外的参数
# docker run -it entrypointtest:V3
CMD>>Hello /bin/echo World
说明:CMD的参数还是被/bin/bash覆盖忽略
# docker run -it entrypointtest:V3 /bin/bash
CMD>>Hello /bin/bash
ENTRYPOINT的shell格式会忽略任何CMD或docker run提供的参数
# cat Dockerfile_ENTRYPOINT
FROM almalinux
MAINTAINER luorf
CMD ["World"]
ENTRYPOINT "/bin/echo" "CMD>>Hello"
# docker build -f ./Dockerfile_ENTRYPOINT -t entrypointtest:V4 .
# docker image ls|grep entrypointtest|grep V4
entrypointtest V4 d04c8b81e661 16 months ago 198MB
说明:shell格式忽略任何CMD参数
# docker run -it entrypointtest:V4
CMD>>Hello
说明:shell格式忽略docker run提供的参数
# docker run -it entrypointtest:V4 /bin/bash
CMD>>Hello
ENTRYPOINT 命令解析变量
# cat Dockerfile_ENTRYPOINT
FROM almalinux
MAINTAINER luorf
ENTRYPOINT ["/bin/sh","-c","echo hello,$HOSTNAME"]
# docker build -f ./Dockerfile_ENTRYPOINT -t entrypointtest:V5 .
# docker image ls|grep entrypointtest|grep V5
entrypointtest V5 04b662e86ab2 16 months ago 198MB
# docker run -it entrypointtest:V5
hello,333f4af8f872
说明:ENTRYPOINT 命令解析变量,覆盖docker run提供的参数
# docker run -it entrypointtest:V5 /bin/bash
hello,da284a108c72
如果想要Docker run 覆盖ENTRYPOINT
# docker run -it --rm --entrypoint /bin/bash entrypointtest:V5
[root@60860fbf496f /]#
3.总结
1)Dockerfile应该至少指定一个 CMD 或ENTRYPOINT;
2)ENTRYPOINT 与CMD很类似,但是ENTRYPOINT 一定不会被忽略,一定会执行;
3)将 Docker 当作可执行程序时, 应该使用 ENTRYPOINT 进行配置; CMD ["param1","param1"] 可以用作 ENTRYPOINT 默认参数(此时ENTRYPOINT 必须使用exec格式);或者用作 Docker 的默认命令;
4)ENTRYPOINT 中的参数始终会被使用,而CMD中的额外参数可以在容器启动(docker run)时动态替换掉;
5)使用了 exec 格式时,docker run 传入的参数会附加到 ENTRYPOINT 之后;
6)建议一般情况下CMD与ENTRYPOINT都使用exec格式.
网友评论