COPY是构建时将文件打包进镜像层,挂载是运行时动态映射宿主机目录;前者生成不可变镜像层,适用于源码、静态资源等交付物,后者实现双向实时读写,适用于日志、数据库等运行态数据,二者阶段不同、目的不同、常配合使用。
COPY 是构建镜像时把文件“打包进镜像层”,挂载(比如 -v 或 --mount)是运行容器时把宿主机目录“动态映射到容器内”,两者阶段不同、目的不同、效果也完全不同。
COPY:只在构建阶段生效,生成不可变镜像层
COPY 指令写在 Dockerfile 里,执行 docker build 时触发。它把本地文件或目录一次性复制进镜像的只读层,成为镜像的一部分。
- 复制后内容固化在镜像中,后续修改宿主机文件不影响已构建的镜像
- 适合放源码、配置模板、静态资源等启动即需、不常变更的内容
- 不支持实时同步,改了宿主机文件必须重新 build 才能更新容器里的内容
- 推荐优先用 COPY 而非 ADD,语义清晰、行为可预测
挂载:运行时绑定,实现宿主机与容器双向可见
挂载通过 docker run 的 -v 或 --mount 参数实现,容器启动时建立宿主机路径与容器内路径的实时关联。
- 容器内看到的是宿主机上真实目录,读写直接作用于宿主机文件系统
- 适合日志目录、数据库数据、配置文件热更新等需要持久化或动态调整的场景
- 容器删了,挂载目录里的数据还在;新容器挂同一目录,就能复用原有数据
- 注意权限和路径一致性,比如 MySQL 容器挂载 /var/lib/mysql 时,宿主机对应目录需有正确属主
什么时候该选哪个?关键看生命周期和变更频率
如果文件属于应用“交付物”——比如编译好的二进制、HTML 页面、环境变量模板——就用 COPY;如果文件属于“运行态数据”——比如用户上传的图片、数据库文件、Nginx 访问日志——就用挂载。
- 前端项目构建产物(dist/)→ COPY 进镜像,轻量且可复现
- 后端服务的日志输出目录 → 挂载到宿主机,方便采集和轮转
- 开发调试时的代码目录 → 挂载源码,改完立刻生效,免 rebuild
- 生产环境的 config.yaml → 若需运维手动调整,建议挂载;若由 CI 统一注入,可用 COPY + ARG 替换
别混淆:COPY 不等于挂载,挂载也不替代 COPY
有人误以为用挂载就能省掉 COPY,结果发现容器启动失败——因为入口命令依赖的启动脚本或依赖库根本没放进镜像。COPY 解决“有没有”,挂载解决“变不变”。两者常配合使用:用 COPY 放运行框架,用挂载放可变数据。
- 例如 Nginx 镜像:COPY nginx.conf(基础配置)+ 挂载 /usr/share/nginx/html(站点内容)
- 再如 Python 应用:COPY requirements.txt 和 pip install → COPY app.py → 挂载 logs/ 目录