为了账号安全,请及时绑定邮箱和手机立即绑定

Dockerfile入门:RUN、CMD和ENTRYPOINT指令全解

Dockerfile 对于自动化创建 Docker 镜像来说至关重要。它们包含一系列指令,如 Docker 使用这些指令来构建镜像。其中,RUN、CMD 和 ENTRYPOINT 这些指令对于定义 Docker 容器的行为至关重要。理解这些指令之间的区别,并知道何时使用它们,是有效管理 Dockerfile 的关键。如 RUN(执行指令)、CMD(容器默认执行指令)、ENTRYPOINT(容器启动指令)。

— 使用 Dockerfile 构建镜像

在详细了解 RUNCMDENTRYPOINT 之前,我们先快速回顾一下如何使用 Dockerfile 创建一个镜像以及如何使用该镜像运行一个容器。

要从 Dockerfile 创建 Docker 影像,请切换到包含 Dockerfile 的目录,然后运行以下命令:

# 要构建一个带有自定义名称的 Docker 镜像,可以使用下面的命令
docker build -t my-image-name .

这个命令使用当前目录中的 Dockerfile 来构建一个带有标签 my-image-name 的镜像 (image)。

— 使用镜像启动容器

你可以使用以下命令来启动一个容器,一旦你有了镜像。

    docker run my-image-name
    # 下面的命令用于运行指定的Docker镜像 # 运行名为my-image-name的镜像

此命令会从 my-image-name 镜像启动一个新的容器。你可以添加其他选项来自定义容器的行为,比如指定要运行的其他命令。

我们现在来看看 Dockerfile 指令:RUNCMDENTRYPOINT

🔸 开始运行的指示

RUN 指令用于构建 Docker 镜像时执行命令。每个 RUN 命令都会创建一个新的镜像层,命令执行后的容器状态会被提交到镜像中。这通常用来安装软件包或设置环境。

例子:

     # 编辑Dockerfile  

    FROM ubuntu:latest  
    RUN apt-get update && apt-get install -y nginx
在当前目录下使用 Docker 构建一个镜像,命名为 my-image。
# docker build -t my-image .

💎 给大家推荐一下 RUN

  • 尽量减少层次:使用 && 将多个命令合并到一个 RUN 指令中,以减少层次并保持镜像更小。
  • 合理安排 RUN 命令:以利用 Docker 的缓存机制。将变化较少的命令放在前面。
🔸 请依照指令行事。

CMD 指令用来指定默认启动命令,该命令在从镜像启动容器时运行。与 RUN 不同,CMD 不会在构建过程中执行命令。相反,它设置了容器的默认启动行为。如果您在启动容器时提供了命令,它将覆盖默认命令。

例子:

FROM ubuntu:最新版本  
CMD ["echo", "Hello, World!"]  //命令用于输出 'Hello, World!' 到控制台

💎 CMD推荐事项:

  • 使用默认设置:使用 CMD 指定默认命令或参数,这些默认值可以在运行时被替换。
  • 优先使用 exec 形式:使用 exec 形式(即数组语法)以确保正确的信号处理并避免与 shell 相关的问题出现。
注释:ENTRYPOINT 指令

ENTRYPOINT 指令配置容器以作为可执行文件启动。它定义了容器启动时始终执行的命令,并且除非使用 --entrypoint 标志,否则该命令不会被命令行参数替换。

例子:

FROM ubuntu:latest  
# 尾随并显示文件的更新
ENTRYPOINT ["tail", "-f"]

关于 ENTRYPOINT 的推荐:

  • 用于固定入口点:使用 ENTRYPOINT 让容器始终运行特定的应用或指令。
  • 结合 CMD 使用:将 ENTRYPOINT 与 CMD 结合使用,以提供默认参数值,这些参数可以被覆盖。

如果 CMD 或 ENTRYPOINT 缺失会发生什么?

如果 Dockerfile 没有包含 CMDENTRYPOINT 指令,容器启动时将没有默认的执行命令(除非源镜像中定义了默认的 shell 脚本、bash 脚本或其他命令,这取决于所使用的原始镜像)。因此,容器会在启动后立即退出,因为没有进程在运行

从最新的Ubuntu镜像开始,更新软件包列表并安装nginx。这行命令告诉Docker,我们希望从最新的Ubuntu官方镜像开始,更新系统包列表以确保所有软件是最新版本,然后安装nginx服务器。

容器启动了 /bin/bash 脚本并然后立即退出了

此外,即使指定了CMDENTRYPOINT命令,如果它们运行的命令很快完成,容器会在命令执行结束后立即停止。因此,命令应该是持续运行的,以防止容器退出。

— 一个短暂命令的例子

     FROM ubuntu:latest  
    CMD ["echo", "这条命令将会输出信息并立即退出"]

在这个场景中,容器启动,打印消息,然后因为 echo 命令执行很快,会立即停止运行。

— 一个长时间运行的命令的例子,比如:
</TRANSLATION>

从最新的 Ubuntu 镜像创建一个新的容器,并在容器启动时运行 tail -f /dev/null 命令,该命令会持续读取 /dev/null 文件的输出(实际上不会显示任何内容,因为 /dev/null 是一个空设备文件)。

在这里面,tail -f /dev/null 命令会让容器持续运行,因为它会一直等待输入,从而使进程保持运行。

🔸 壳命令 vs. 执行命令

Docker 让你可以用两种方式指定命令:shell 方式和 exec 方式。了解这些方式的区别对于编写有效的 Dockerfile 很重要。

— Shell 形式下:命令被写成字符串形式并在 shell 中执行。这允许你使用 shell 的特性,比如环境变量的扩展,但可能会导致信号处理不当和转义字符的问题。

例子:

FROM ubuntu:最新版本
CMD echo "你好,世界!"

命令以 shell “/bin/sh -c” 开头

— 执行格式:命令以 JSON 数组的形式指定,这意味着它会直接执行,不经过 shell。这种格式因其可预测性和更好的信号处理而更受欢迎。

例子如下:

# 从ubuntu:latest镜像创建一个新的容器
FROM ubuntu:latest   
# CMD命令用于在容器启动时执行echo命令,输出"Hello, World!"信息
CMD ["echo", "Hello, World!"]

这个命令可以直接运行,不需要经过 shell。

关于 Shell 语法和 Exec 形式 的推荐

  • 建议使用 exec 格式:在 CMD 和 ENTRYPOINT 中使用 exec 格式,以确保正确的信号处理机制并避免与 shell 相关的潜在问题。
🔸 如何覆盖 CMD 和 ENTRYPOINT(指令)

— 覆盖默认命令 :您可以通过在运行容器时提供一个命令来覆盖 CMD 指令。这是通过在 docker run 命令后面加上新命令来实现的。

例如:

运行最新的Ubuntu镜像并启动bash shell,就像这样: `docker run ubuntu:latest /bin/bash`

— 覆盖 ENTRYPOINT 指令 : 运行容器时,请使用 --entrypoint 标志,后面跟上新的指令。

例子:

     docker run --entrypoint /bin/bash ubuntu:latest
使用 Docker 运行 Ubuntu 容器并进入 bash shell
🔸 结合 CMD 和 ENTRYPOINT 的技巧

ENTRYPOINT 和 CMD 可以一起使用来创建可以运行的灵活 Docker 镜像。当它们一起使用时:

  • ENTRYPOINT 指定要运行的可执行程序。
  • CMD 提供该可执行程序的默认命令行参数。

比如:

ENTRYPOINT ["python", "app.py"]  
CMD ["--端口", "8000"]

在这种情况里:

  • 容器将始终运行命令 python app.py
  • 默认情况下,它会使用端口参数 --port 8000
  • 您可以在运行时更改端口
    docker run myimage --port 9000

在终端中输入以上命令来运行 Docker 镜像并指定端口为 9000。

这里有一个简单的例子,比如:

FROM ubuntu:latest  
# 使用tail命令持续监控/dev/null文件  
ENTRYPOINT ["tail"]  
CMD ["-f", "/dev/null"]

命令行参数是由ENTRYPOINT (tail) 和 CMD (-f /dev/null) 组合而成的。

🔸 何时使用及差异:啥时候用

RUN 与 CMD/ENTRYPOINT 的区别:

  • RUN 在构建镜像时执行命令。

  • CMD 和 ENTRYPOINT 指定容器启动时要运行的命令。
  1. CMD 与 ENTRYPOINT 之间的区别:
  • 可以通过在 docker run 中提供命令轻松覆盖 CMD。
  • ENTRYPOINT 更难被覆盖或替换(除非使用 --entrypoint 标志),并且通常用于那些需要始终运行的命令。
  1. 合并 CMD 和 ENTRYPOINT:
  • 使用 ENTRYPOINT 来设定主命令,并使用 CMD 来设定默认参数,并且这样做可以在运行时灵活传递参数,同时保持主命令的固定。
全球性的建议
  1. 定义默认行为:应始终定义 CMD 或 ENTRYPOINT 以确保容器具有可预测的默认行为。这对于需要一致性的生产环境尤为重要。
  2. 结合 ENTRYPOINT 和 CMD:通常,结合使用 ENTRYPOINT 和 CMD 是有好处的。ENTRYPOINT 可以指定可执行文件,而 CMD 提供默认参数。这允许灵活性,并确保容器运行预期的应用程序。
  3. 优化效率:高效使用 RUN 命令以最小化镜像大小和构建时间。通过策略性地安排命令来利用 Docker 的缓存机制。
结论

通过掌握并恰当使用RUN、CMD、ENTRYPOINT以及shell和exec形式的区别,你可以创建高效且灵活的Docker镜像,以满足应用程序的需要。

谢谢大家的阅读 📝,下期见啦 🚀!

如果你觉得这篇文章有趣且有帮助,为什么不点个赞就走呢 😔?至少可以通过点赞、留言并关注我来表示你的支持吧 👋

如果你有任何关于这个博客的问题或意见,请随时通过LinkedIn与我联系。

💬 领英https://www.linkedin.com/in/ahmed-mansouri-a54637141

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消