Dockerfile中RUN CMD ENTRYPOINT都能够用于执行命令

  • RUN命令执行命令并创建新的镜像层,通常用于安装软件包
  • CMD命令设置容器启动后默认执行的命令及其参数,但CMD设置的命令能够被docker run命令后面的命令行参数替换
  • ENTRYPOINT配置容器启动时的执行命令(不会被忽略,一定会被执行,即使运行 docker run时指定了其他命令)

Shell格式和Exec格式运行命令

两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式

  • Shell格式: ,例如:apt-get install python3
  • Exec格式: [“executable”, “param1”, “param2”, …],例如: [“apt-get”, “install”, “python3”]

CMD和ENTRYPOINT推荐使用Exec格式,因为指令可读性更强,更容易理解,可以实现k8s容器应用优雅关闭,RUN则两种格式都可以

Exec与Shell格式区别

编写dockfile文件,以shell格式编写,并且验证

[root@nginx test]# cat Dockerfile 
FROM busybox
ENV name allen
ENTRYPOINT echo "hello,$name"
[root@nginx test]# docker build -t busybox:v1 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> beae173ccac6
Step 2/3 : ENV name allen
 ---> Running in d66477bce0cf
Removing intermediate container d66477bce0cf
 ---> d14398e9d226
Step 3/3 : ENTRYPOINT echo "hello,$name"
 ---> Running in b5e7000e16c4
Removing intermediate container b5e7000e16c4
 ---> 127222882caf
Successfully built 127222882caf
Successfully tagged busybox:v1

[root@nginx test]# docker run --rm busybox:v1
hello,allen
#在容器启动时设置–rm选项,这样在容器退出时就能够自动清理容器内部的文件系统
#Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量

编写dockfile文件,以execl格式编写,并且验证

[root@nginx test]# cat Dockerfile 
FROM busybox
ENV name allen
ENTRYPOINT echo ["/bin/echo","hello,$name"]
[root@nginx test]# docker build -t busybox:v1 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
---> beae173ccac6
Step 2/3 : ENV name allen
---> Using cache
---> d14398e9d226
Step 3/3 : ENTRYPOINT echo ["/bin/echo","hello,$name"]
---> Running in 022b942d55ef
Removing intermediate container 022b942d55ef
---> 046b1de3539c
Successfully built 046b1de3539c
Successfully tagged busybox:v1
[root@nginx test]# docker run --rm busybox:v1  
[/bin/echo,hello,allen]

修改Dockerfile

[root@nginx test]# cat Dockerfile 
FROM busybox
ENV name allen
ENTRYPOINT ["/bin/echo","hello,$name"]
[root@nginx test]# docker build -t busybox:v1 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> beae173ccac6
Step 2/3 : ENV name allen
 ---> Using cache
 ---> d14398e9d226
Step 3/3 : ENTRYPOINT ["/bin/echo","hello,$name"]
 ---> Running in 68427d63b543
Removing intermediate container 68427d63b543
 ---> 913398a6c730
Successfully built 913398a6c730
Successfully tagged busybox:v1
[root@nginx test]# docker run --rm busybox:v1  
hello,$name

再次修改Dockerfile

[root@nginx test]# cat Dockerfile 
FROM busybox
ENV name allen
ENTRYPOINT [ "/bin/sh","-c","/bin/echo hello,$name"]
[root@nginx test]# docker build -t busybox:v1 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> beae173ccac6
Step 2/3 : ENV name allen
 ---> Using cache
 ---> d14398e9d226
Step 3/3 : ENTRYPOINT [ "/bin/sh","-c","/bin/echo hello,$name"]
 ---> Running in 3a7b3f6d3696
Removing intermediate container 3a7b3f6d3696
 ---> e3b6cce71583
Successfully built e3b6cce71583
Successfully tagged busybox:v1
[root@nginx test]# docker run --rm busybox:v1  
hello,allen

可见,Shell格式底层会调用/bin/sh -c来执行命令,而exec格式不会。系统调用exec是以新的进程去替代原来的进程,但进程的PID不变,使用exec可以实现k8s容器应用优雅关闭

Run命令

RUN 指令通常用于安装应用和软件包,RUN 在当前镜像的顶部执行命令,并通过创建新的镜像层,Dockerfile 中常常包含多个 RUN 指令

RUN apt-get update && apt-get install -y \  
 bzr \
 cvs \
 git \
 mercurial \
 subversion

CMD命令

CMD 指令允许用户指定容器的默认执行的命令,此命令会在容器启动且 docker run 没有指定其他命令时运行

CMD echo "Hello world"

运行容器 docker run -it [image] 将输出

Hello world

当后面加上一个命令,比如 docker run -it [image] /bin/bash,CMD 会被忽略掉,命令 bash将被执行

root@10a32dc7d3d3:/#

ENTRYPOINT命令

ENTRYPOINT的Exec格式用于设置容器启动时要执行的命令及其参数,同时可通过CMD命令或者命令行参数提供额外的参数,ENTRYPOINT中的参数始终会被使用,这是与CMD命令不同的一点

ENTRYPOINT ["/bin/echo", "Hello"]  

当容器通过 docker run -it [image] 启动时,输出为

Hello

而如果通过 docker run -it [image] CloudMan 启动,则输出为

Hello CloudMan

将Dockerfile修改为

ENTRYPOINT ["/bin/echo", "Hello"]  
CMD ["world"]

当容器通过 docker run -it [image] 启动时,输出为

Hello world

而如果通过 docker run -it [image] CloudMan 启动,输出依旧为

Hello CloudMan

ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉

总结

  • 使用RUN指令安装应用和软件包,构建镜像
  • 如果Docker镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec格式的 ENTRYPOINT指令,CMD可为ENTRYPOINT提供额外的默认参数,同时可利用 docker run命令行替换默认参数
  • 如果想为容器设置默认的启动命令,可使用CMD指令,用户可在 docker run命令行中替换此默认命令
  • Shell格式底层会调用/bin/sh -c来执行命令,而exec格式不会,系统调用exec是以新的进程去替代原来的进程,但进程的PID不变,使用exec可以实现k8s容器应用优雅关闭
文章作者: 鲜花的主人
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 爱吃可爱多
Docker Docker
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝