For the complete documentation index, see llms.txt. This page is also available as Markdown.

7.2 COPY 复制文件

何时使用 COPY

COPY 是在构建镜像时,将构建上下文(Dockerfile 所在目录及其子目录)中的文件或目录复制到容器内的指令。它是处理应用代码、配置文件最常用的方式。

典型场景:

  • 复制应用源码:COPY . /app

  • 复制配置文件:COPY nginx.conf /etc/nginx/nginx.conf

  • 复制静态资源:COPY public /app/public

为什么 COPY 比 ADD 更值得推荐? 笔者建议在 90% 的情况下使用 COPY。原因是 COPY 的语义更清晰——它就是简单地复制文件。而 ADD 有额外的功能(自动解压、支持 URL),这些功能往往会带来意外的行为。除非你明确需要 ADD 的自动解压功能,否则用 COPY。详见 7.3 ADD 指令 中的详细对比。

7.2.1 基本语法

COPY [选项] <源路径>... <目标路径>
COPY [选项] ["<源路径1>", "<源路径2>", ... "<目标路径>"]

COPY 指令将构建上下文中的文件或目录复制到镜像内。


7.2.2 基本用法

复制单个文件

复制多个文件

复制目录

⚠️ 注意:复制目录时,复制的是目录的 内容,不包含目录本身。


7.2.3 通配符规则

COPY 支持 Go 的 filepath.Match 通配符规则:

通配符
说明
示例

*

匹配任意字符序列

*.json

?

匹配单个字符

config?.json

[abc]

匹配括号内任一字符

[abc].txt

[a-z]

匹配范围内字符

file[0-9].txt


7.2.4 目标路径

绝对路径

相对路径:基于 WORKDIR

自动创建目录

如果目标目录不存在,Docker 会自动创建:


7.2.5 修改文件所有者

使用 --chown 选项设置文件的用户和组:

💡 结合 USER 指令使用,确保应用以非 root 用户运行。


7.2.6 保留文件元数据

COPY 会保留源文件的元数据:

  • 读、写、执行权限

  • 修改时间

这对于脚本文件特别重要:


7.2.7 COPY vs ADD

特性
COPY
ADD

复制本地文件

自动解压 tar

支持 URL

✅ (不推荐)

推荐程度

推荐

⚠️ 特殊场景使用

笔者建议:除非需要自动解压 tar 文件,否则始终使用 COPY。明确的行为比隐式的魔法更好。


7.2.8 多阶段构建中的 COPY

从其他构建阶段复制

--link 的优势:

  • 更高效利用构建缓存

  • 并行化构建过程

  • 加速多阶段构建

⚠️ 注意:使用 --link 需要满足以下条件:

  • 启用 BuildKit(Docker Engine 23.0+ 默认启用)

  • Dockerfile 语法版本 1.4 或更高(在首行声明 # syntax=docker/dockerfile:1

  • 目标路径在前序指令中应不存在或为空目录


7.2.9 dockerignore

使用 .dockerignore 排除不需要复制的文件:

这可以:

  • 减小构建上下文大小

  • 加速构建

  • 避免复制敏感文件


7.2.10 最佳实践

1. 利用缓存,先复制依赖文件

2. 使用 .dockerignore

3. 明确复制路径


🔥 踩坑实录

某公司在优化 Node.js 应用的 Docker 镜像时,发现构建出来的镜像体积超过了 2GB,远远超过生产部署的需求。排查发现,Dockerfile 中使用了 COPY . . 把整个构建上下文复制进镜像,导致 node_modules/.git/ 目录和大量测试数据全部被打包进镜像。最初他们没有创建 .dockerignore 文件,默认会复制所有文件。解决方案是添加一个 .dockerignore 文件,排除这些不必要的目录,使镜像缩小到了 200MB。这个教训深刻地说明了:.dockerignore.gitignore 一样重要,应该在项目初始化时就创建,而不是等到出现问题时才想起来。建议的标准做法是先复制 package.jsonpackage-lock.json 安装依赖,再复制应用代码,同时在 .dockerignore 中明确列出 node_modules.git、test 目录等。

最后更新于