Skip to content

Dockerfile中RUN、CMD、ADD、COPY 指令

在 Dockerfile 中,RUNCMDADDCOPY 是常用的指令,但它们的作用和适用场景有显著区别。以下是详细对比及示例:


1. RUN 命令 vs CMD 命令

核心区别

特性RUNCMD
作用时机镜像构建阶段执行命令(如安装软件、编译代码)容器启动时指定默认执行的命令或参数
执行次数每个 RUN 生成一个镜像层一个 Dockerfile 中只能有一个生效的 CMD(多个时以最后一个为准)
覆盖性无法被覆盖,固化在镜像中可以被 docker run 后的参数覆盖
典型用途安装依赖、创建目录、修改文件权限等定义容器启动后运行的默认程序

示例

dockerfile
# RUN 示例:构建阶段安装 Python
RUN apt-get update && apt-get install -y python3

# CMD 示例:容器启动时运行 Python 脚本
CMD ["python3", "app.py"]

细节说明

  • RUN 的两种格式

    dockerfile
    # Shell 格式(默认使用 /bin/sh -c 执行)
    RUN echo "Hello" > /tmp/hello.txt
    
    # Exec 格式(直接执行命令,避免 shell 解析)
    RUN ["/bin/bash", "-c", "echo 'Hello' > /tmp/hello.txt"]
  • CMD 的三种格式

    dockerfile
    # Exec 格式(推荐,避免 shell 干扰信号传递)
    CMD ["nginx", "-g", "daemon off;"]
    
    # Shell 格式(实际会包装成 /bin/sh -c)
    CMD nginx -g "daemon off;"
    
    # 为 ENTRYPOINT 提供默认参数
    ENTRYPOINT ["nginx"]
    CMD ["-g", "daemon off;"]

2. ADD 命令 vs COPY 命令

核心区别

特性ADDCOPY
功能扩展支持自动解压 本地 tar 文件,支持从 URL 下载文件仅复制本地文件/目录到镜像中
行为透明性可能隐含解压或下载操作,需谨慎使用行为明确,仅复制文件
推荐场景需要解压 tar 包或从 URL 获取文件普通文件复制(更推荐优先使用)

示例

dockerfile
# ADD 示例:自动解压本地 tar 包到镜像的 /app 目录
ADD app.tar.gz /app/

# ADD 示例:从 URL 下载文件到镜像(不推荐,需注意网络稳定性)
ADD https://example.com/file.txt /tmp/

# COPY 示例:复制本地文件到镜像的 /app 目录
COPY app.py /app/
COPY requirements.txt /app/

细节说明

  • ADD 的隐式行为

    • 如果源路径是 本地 tar 文件(如 .tar, .tar.gz),ADD 会自动解压到目标路径。
    • 若源路径是 URLADD 会尝试下载文件(但下载后的文件权限默认是 600,需手动调整)。
  • COPY 的明确性

    • 仅支持本地文件复制,无副作用,更符合最小化操作原则。
    • 支持多阶段构建中的 --from 参数,从其他阶段复制文件。

3. 最佳实践总结

  1. 优先使用 COPY

    • 除非需要 ADD 的解压或 URL 下载功能,否则优先用 COPY 保证行为透明。
  2. 减少 RUN 的层数

    • 合并多个 RUN 命令以减少镜像层数(例如用 && 连接命令):
      dockerfile
      RUN apt-get update \
          && apt-get install -y python3 \
          && rm -rf /var/lib/apt/lists/*
  3. 合理选择 CMD 格式

    • 使用 Exec 格式避免 Shell 信号传递问题(例如容器优雅退出)。
  4. 谨慎使用 ADD 的 URL 功能

    • 下载文件建议在 RUN 中结合 wgetcurl,以便处理错误和权限。

完整 Dockerfile 示例

dockerfile
# 使用基础镜像
FROM ubuntu:22.04

# 安装依赖(RUN)
RUN apt-get update \
    && apt-get install -y python3 \
    && rm -rf /var/lib/apt/lists/*

# 复制本地文件(COPY)
COPY app.py /app/
COPY requirements.txt /app/

# 解压 tar 包(ADD)
ADD data.tar.gz /app/data/

# 设置工作目录
WORKDIR /app

# 定义容器启动命令(CMD)
CMD ["python3", "app.py"]

通过合理选择指令,可以优化镜像构建效率、减少体积,并确保容器行为符合预期。

/src/technology/dateblog/2025/05/20250508-dockerfile%E4%B8%ADrun%E3%80%81cmd%E3%80%81add%E3%80%81copy-%E6%8C%87%E4%BB%A4.html