Dockerfile RUN CMD ENTRYPOINT区别
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容器应用优雅关闭