mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-03-10 11:54:37 +00:00
4.9 KiB
4.9 KiB
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 优化缓存(BuildKit)
# 使用 --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 ./ |
延伸阅读
- ADD 指令:复制和解压
- WORKDIR 指令:设置工作目录
- 多阶段构建:优化镜像大小
- 最佳实践:Dockerfile 编写指南