深入解析Docker镜像构建:RUN, CMD, 与 ENTRYPOINT 的全面解析

在 Dockerfile 中,RUN、CMD 和 ENTRYPOINT 这三条指令看起来相似,它们的作用都是在 Docker 镜像构建过程中运行指定的命令。有时候很容易造成混淆,接下来我们来详细探讨它们之间的区别。

RUN、CMD、ENTRYPOINT的作用

  • RUN:执行命令并创建新的镜像层。当你需要在镜像构建过程中安装软件包或应用程序时,就会用到 RUN。每执行一次 RUN 就会在镜像上添加一个新的层。

  • CMD:设置容器启动后默认执行的命令及其参数。不过,CMD 指定的命令可以通过 docker run 命令行参数来覆盖。它主要用于为容器设定默认启动行为。如果 Dockerfile 中有多个 CMD 指令,只有最后一个生效。

  • ENTRYPOINT:配置容器启动时运行的命令,功能上与 CMD 类似,但有一个关键区别------即使在 docker run 时指定了其他命令,ENTRYPOINT 也不会被忽略,而是会与这些命令结合使用(除非使用 --entrypoint 覆盖)。当容器作为应用程序或服务运行时,推荐使用 ENTRYPOINT,并且最好采用 Exec 格式。

我们可以通过两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell格式和Exec格式,这两种格式在使用上有一些微妙的差异。

Shell格式 和 Exec格式

Docker中的 RUN, CMD, 和 ENTRYPOINT 指令都可以采用两种不同的运行格式来指定要执行的命令:

Shell格式

Shell格式如下所示:

xml 复制代码
<instruction> <command>

例如:

bash 复制代码
RUN apt-get install python3
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"

当执行命令时,Shell 格式的底层会使用 /bin/sh -c <command>。当你以Shell格式运行命令时,由 ENV 命令定义的环境变量可以被获取到。

bash 复制代码
ENV name Cloud Man
ENTRYPOINT echo "Hello, $name"

输出:

Hello, Cloud Man

Exec格式

Exec格式如下所示:

css 复制代码
<instruction> ["executable", "param1", "param2", ...]

例如:

css 复制代码
RUN ["apt-get", "install", "python3"]
CMD ["/bin/echo", "Hello world"]
ENTRYPOINT ["/bin/echo", "Hello world"]

当执行命令时,<command>将被直接调用,不会被shell解析。在 ENV 中定义的环境变量也没法获取到。

bash 复制代码
ENV name Cloud Man

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

输出:

bash 复制代码
Hello, $name

推荐使用Exec格式进行CMD和ENTRYPOINT的指定,因为这样指令更易于阅读和理解。

RUN

RUN命令通常用于安装应用程序和软件包。RUN 在当前镜像之上执行命令,并通过创建一个新的镜像层。Dockerfile 通常包含多个RUN指令。

CMD

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

  1. 如果docker run指定了另一个命令,CMD指定的默认命令将被忽略。

  2. 如果Dockerfile中有多个CMD指令,只有最后一个CMD有效。

CMD有三种格式:

  • Exec格式:CMD ["executable","param1","param2"]

  • CMD ["param1", "param2"],这种格式与ENTRYPOINT结合使用,以提供额外的参数

  • Shell格式:CMD command param1 param2

推荐使用Exec格式,因为它提供了更好的可读性。

ENTRYPOINT

The ENTRYPOINT directive allows the container to run as an application or service.

ENTRYPOINT在指定要执行的命令及其参数方面与CMD相似。不同之处在于,即使在运行docker run时指定了其他命令,ENTRYPOINT也不会被忽略,并且会被执行。

ENTRYPOINT有两种格式:

  • Exec格式:ENTRYPOINT ["executable", "param1", "param2"] 这是ENTRYPOINT推荐使用的格式。

  • Shell格式:ENTRYPOINT command param1 param2

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

css 复制代码
ENTRYPOINT ["/bin/echo", "Hello"]

CMD ["world"]

# Output
Hello world

请注意,ENTRYPOINT的Shell格式会忽略CMD或docker run提供的任何参数。

bash 复制代码
FROM busybox
ENTRYPOINT echo hello
CMD world


hello

Docker中的 --entrypoint 命令行选项允许你在运行容器时覆盖Docker镜像中指定的ENTRYPOINT指令。

ini 复制代码
$ docker run --entrypoint="path/to/custom/entrypoint" imagename

默认情况下,当你运行一个Docker容器时,会执行镜像中ENTRYPOINT指令指定的命令。但是,如果你想覆盖这种行为,可以使用 --entrypoint 选项来指定一个不同的入口点来使用。有时这对容器内部环境问题的调试很有帮助。

总结

  1. 使用 RUN 命令来安装应用程序和包,并创建新的镜像层。

  2. 如果Docker镜像的目的是运行一个应用程序或服务,例如运行 MySQL,那么应该优先使用 Exec 格式的 ENTRYPOINT 命令。CMD 可以为 ENTRYPOINT 提供额外的默认参数,并且这些默认参数可以被 docker run 命令行替换。

  3. 如果你想为容器设置默认的启动命令,可以使用 CMD 命令。用户可以在 docker run 命令行中覆盖这个默认命令。

相关推荐
夜月行者1 小时前
如何使用ssm实现基于SSM的宠物服务平台的设计与实现+vue
java·后端·ssm
Yvemil71 小时前
RabbitMQ 入门到精通指南
开发语言·后端·ruby
sdg_advance1 小时前
Spring Cloud之OpenFeign的具体实践
后端·spring cloud·openfeign
猿java2 小时前
使用 Kafka面临的挑战
java·后端·kafka
碳苯2 小时前
【rCore OS 开源操作系统】Rust 枚举与模式匹配
开发语言·人工智能·后端·rust·操作系统·os
theo.wu2 小时前
使用Buildpacks构建Docker镜像
运维·docker·容器
kylinxjd2 小时前
spring boot发送邮件
java·spring boot·后端·发送email邮件
2401_857439696 小时前
Spring Boot新闻推荐系统:用户体验优化
spring boot·后端·ux
进击的女IT6 小时前
SpringBoot上传图片实现本地存储以及实现直接上传阿里云OSS
java·spring boot·后端
一 乐8 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习