Dockerfile构建中ADD/COPY指令

COPYADD 指令如果目标路径不存在,会自动创建目标目录(包括多级目录)


ADD/COPY

Docker 在执行:

1
COPY src /app/

1
ADD src /app/

逻辑是:

    1. 如果 /app/ 不存在,Docker 会自动创建它;
    1. 如果 /app/ 存在且是目录,则文件复制进该目录;
    1. 如果 /app 不存在且目标路径不以 / 结尾,例如:
    1
    COPY src /app

    /app 被视为文件名(若上级目录存在),否则 Docker 也会创建缺失的目录结构再复制。


验证

示例 1:复制目录

1
COPY ./config /opt/app/conf/

如果 /opt/app/conf/ 不存在,Docker 会创建整个路径 /opt/app/conf/

示例 2:复制单个文件

1
COPY ./my.conf /etc/nginx/my.conf

如果 /etc/nginx/ 不存在,也会被自动创建,然后再放进去。


⚠️ 注意事项

  1. 不会创建源路径COPY 只会创建目标路径。

  2. 自动创建的目录权限

    • 默认继承当前镜像的 WORKDIR 或根目录 / 的权限;
    • 可以通过 RUN mkdir -p /path && chown user:user /path 预设权限。
  3. 推荐习惯
    对生产镜像或权限敏感场景,显式创建目录并设置权限,例如:

    1
    2
    RUN mkdir -p /app/conf && chown appuser:appuser /app/conf
    COPY conf/ /app/conf/

Dockerfile 中 COPY / ADD 行为流程图

flowchart TD
    A[Docker build 开始] --> B[执行 COPY / ADD 指令]
    B --> C{源路径存在?}
    
    C -- 否 --> D[构建失败
Source not found] C -- 是 --> E{目标路径存在?} E -- 是 --> F{目标是目录?} F -- 是 --> G[复制内容进入目录] F -- 否 --> H[覆盖或创建目标文件] E -- 否 --> I[自动创建目标目录结构] I --> G G --> J[写入镜像层] H --> J J --> K[构建继续下一层]

可以这样理解构建过程:

  • 源文件必须存在,否则构建直接失败;目标路径不存在时,Docker 会帮你递归创建目录,然后再复制文件;
  • 如果目标已经存在,就根据是目录还是文件决定是“放进去”还是“覆盖”。