Files
docker_practice/07_dockerfile/7.2_copy.md
Baohua Yang b44c9acd6c Restruct
2026-02-09 12:56:12 -08:00

5.2 KiB
Raw Blame History

7.2 COPY 复制文件

基本语法

具体内容如下:

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

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


基本用法

复制单个文件

具体内容如下:

## 复制文件到指定目录

COPY package.json /app/

## 复制文件并重命名

COPY config.json /app/settings.json

复制多个文件

具体内容如下:

## 复制多个指定文件

COPY package.json package-lock.json /app/

## 使用通配符

COPY *.json /app/
COPY src/*.js /app/src/

复制目录

具体内容如下:

## 复制整个目录的内容(不是目录本身)

COPY src/ /app/src/

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

构建上下文:              镜像内:
src/                     /app/src/
├── index.js      →      ├── index.js
└── utils.js             └── utils.js

通配符规则

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

通配符 说明 示例
* 匹配任意字符序列 *.json
? 匹配单个字符 config?.json
[abc] 匹配括号内任一字符 [abc].txt
[a-z] 匹配范围内字符 file[0-9].txt
COPY hom* /mydir/       # home.txt, homework.md 等
COPY hom?.txt /mydir/   # home.txt, homy.txt 等
COPY app[0-9].js /app/  # app0.js ~ app9.js

目标路径

绝对路径

具体内容如下:

COPY app.js /usr/src/app/

相对路径(基于 WORKDIR

具体内容如下:

WORKDIR /app
COPY package.json ./        # 复制到 /app/package.json
COPY src/ ./src/            # 复制到 /app/src/

自动创建目录

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

## /app/config/ 不存在也会自动创建

COPY settings.json /app/config/

修改文件所有者

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

## 使用用户名和组名

COPY --chown=node:node package.json /app/

## 使用 UID 和 GID

COPY --chown=1000:1000 . /app/

## 只指定用户

COPY --chown=node . /app/

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


保留文件元数据

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

  • 读、写、执行权限
  • 修改时间

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

## start.sh 的可执行权限会被保留

COPY start.sh /app/

COPY vs ADD

特性 COPY ADD
复制本地文件
自动解压 tar
支持 URL (不推荐)
推荐程度 推荐 ⚠️ 特殊场景使用
## 推荐:使用 COPY

COPY app.tar.gz /app/
RUN tar -xzf /app/app.tar.gz

## ADD 会自动解压(行为不明显,不推荐)

ADD app.tar.gz /app/

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


多阶段构建中的 COPY

从其他构建阶段复制

具体内容如下:

## 构建阶段

FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

## 生产阶段

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

具体内容如下:

## 使用 --link 后,文件以独立层添加,不依赖前序指令

COPY --link --from=builder /app/dist /usr/share/nginx/html

--link 的优势:

  • 更高效利用构建缓存
  • 并行化构建过程
  • 加速多阶段构建

.dockerignore

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

## .dockerignore

node_modules
.git
.env
*.log
Dockerfile
.dockerignore

这可以:

  • 减小构建上下文大小
  • 加速构建
  • 避免复制敏感文件

最佳实践

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

具体内容如下:

## ✅ 好:先复制依赖定义,再安装,最后复制代码

COPY package.json package-lock.json ./
RUN npm install
COPY . .

## ❌ 差:一次性复制所有文件,代码变更会导致重新 npm install

COPY . .
RUN npm install

2. 使用 .dockerignore

具体内容如下:

## 确保 node_modules 不被复制

COPY . .
## .dockerignore 中应包含 node_modules

具体内容如下:

3. 明确复制路径

具体内容如下:

## ✅ 好:明确的路径

COPY src/ /app/src/
COPY package.json /app/

## ❌ 差:过于宽泛

COPY . .

本章小结

操作 示例
复制文件 COPY app.js /app/
复制多个文件 COPY *.json /app/
复制目录内容 COPY src/ /app/src/
修改所有者 COPY --chown=node:node . /app/
从构建阶段复制 COPY --from=builder /app/dist ./

延伸阅读