第 16 篇、90% Docker 新手都栽在这!Compose 镜像构建的 5 个致命坑,新手直接抄
文章目录
90% Docker 新手都栽在这!Compose 镜像构建的 5 个致命坑,新手直接抄

凌晨两点,你还在对着服务器敲命令。
改了一下午的业务代码,终于要更新到测试环境了。你信心满满敲下docker compose up -d,结果屏幕直接报错:“镜像构建失败,COPY文件找不到。”
如果,你也有过这样的崩溃时刻?别慌。
本文是《Docker 实战》系列第16篇,我会结合Docker官方最新规范,把Compose镜像构建、服务更新的底层逻辑讲透,再把90%新手必踩的致命坑全部拆解。
全系列文章覆盖 Docker 基础、容器、镜像、仓库、网络核心实战,再到数据持久化、Dockerfile、Docker Compose 全场景落地,全程保姆级实战教学。
我已经把全系列文章都转换成 PDF 版本,随时随地可查。文章最后提供了领取方式。
文末还给大家准备了专属新手福利:我亲手整理的**《Docker Compose 生产级最佳实践手册》+ 《10 套开箱即用 Compose 配置文件》。**
90% 新手都被误导的 2 个核心误区(官方已废弃,别再用了)
在正式讲内容之前,先纠正两个网上老教程传烂了的错误用法,这是你后续所有操作的基础,也是绝大多数新手踩坑的根源:
误区1:还在用docker-compose(横杠)命令?官方早已废弃
很多老教程里教的docker-compose up/down,是Docker Compose V1版本的旧命令,早在2023年就已经停止维护,新版Docker已经完全移除了该命令。
✅ 官方正确用法:用docker compose(空格)命令,这是V2版本的官方标准写法,所有新版Docker都自带,无需额外安装,后续所有命令均以此为准。
误区2:compose文件开头必写version: "3.8"?完全没必要
Docker官方早已明确说明:顶层 version 字段已经完全废弃,仅做向后兼容,使用会触发过时警告。Compose会自动使用最新的规范验证配置文件,完全不用再写这个字段,新手直接删掉即可。
✅ 官方正确写法:用顶层name字段指定项目名称,替代废弃的version字段,示例:name: flask-demo
官方定义“镜像构建”的底层核心逻辑
很多新手用了半年Compose,还是没搞懂build和image两个字段的关系,这是所有构建坑的根源。
Docker官方规范明确了Compose镜像处理的核心规则:先拉取、后构建,优先级由pull_policy字段控制。
image字段:定义镜像的最终名称/拉取地址,支持远程私有仓库地址,是镜像的唯一标识;build字段:定义镜像的构建规则,包含构建上下文、Dockerfile路径、构建参数等;- 当一个服务同时定义了
build和image:Compose 会先按拉取策略尝试拉取镜像,若本地/仓库不存在该镜像,再按build规则构建镜像,最终将构建好的镜像打上image字段定义的标签; - 若只定义了
build没定义image:Compose会自动生成项目名-服务名格式的镜像,无法推送到远程仓库,且每次up都会重复校验构建「新手极易踩坑」。
Docker 新手必懂的核心配置项
| 配置项 | 官方定义 | 正确用法 |
|---|---|---|
build.context |
镜像构建的上下文路径,Dockerfile所在目录,相对路径 相对于compose文件所在目录 |
build: ./app(当前compose文件同级的app文件夹为构建上下文) |
build.dockerfile |
自定义Dockerfile文件名, 非默认 Dockerfile时必须填写 |
dockerfile: Dockerfile.dev(开发环境专用构建文件) |
build.args |
构建时的环境变量,仅在镜像构建阶段生效,运行时无效 | args: { PYTHON_VERSION: 3.9-slim } |
image |
镜像的最终标签,支持远程仓库地址 | image: registry.cn-hangzhou.aliyuncs.com/your-namespace/flask-demo:v1.0 |
pull_policy |
镜像拉取/构建策略, 官方定义5种合法值: always/never/missing/build/if_not_present,默认值为 missing |
开发环境用build,生产环境用 missing |
高频核心命令
| 命令 | 官方核心作用 | 新手必用参数 |
|---|---|---|
docker compose build |
构建/重建服务镜像, 不会自动启动容器 |
--no-cache:不使用构建缓存,彻底重新构建;--pull:构建时始终拉取最新的基础镜像;--parallel:并行构建多个服务镜像 |
docker compose pull |
拉取compose.yml中定义的所有服务镜像,不会启动容器 | --ignore-pull-failures:忽略拉取失败的镜像,继续拉取其他;[服务名]:仅拉取指定服务的镜像 |
docker compose push |
将构建好的服务镜像推送到远程镜像仓库 | 前提:服务必须定义带仓库地址的image字段,否则无法推送 |
90% 新手必踩的 5 个镜像构建 & 拉取致命坑
关于 Docker 基础、容器、镜像、仓库、网络核心实战,再到数据持久化、Dockerfile、Docker Compose 全场景落地的更多高频坑,我都整理在了**《Docker 实战》**系列文章里。
关注 我「王二哥的技术笔记」:
- 查看往期全系列文章。
- 及时接收最新更新文章。
本文只讲了 Compose 镜像拉取和构建的核心避坑点,更深度的生产级最佳实践、全场景配置模板,我已经整理成了完整的进阶手册。
私信我,发送关键词【Compose】,即可直接领取全套资料。
坑1:只写了build没写image,导致镜像无法推送、重复构建
现象:每次执行docker compose up都要重新构建镜像,执行push命令提示警告,无法推送镜像到仓库。
错误原因:没有image字段,Compose会自动生成临时镜像名,没有固定标识,无法推送至远程仓库;且每次启动都会校验构建,无法复用本地镜像。
官方正确写法:必须同时定义build和image字段,示例:
name: flask-demo
services:
flask-demo:
image: flask-demo:v1.0 # 固定镜像名称,必写
build: ./app # 构建上下文
ports:
- "8080:5000"
坑2:构建上下文路径写错,导致Dockerfile里的COPY命令持续失败
现象:构建镜像时提示COPY failed: file not found,但文件明明在本地存在。
错误原因:没搞懂「构建上下文是Docker命令执行的根目录」,新手常把context写成Dockerfile所在的子目录,却在Dockerfile里COPY上下文外的文件,Docker根本找不到对应文件。
官方正确写法:
-
构建上下文始终以compose文件所在目录为根目录,相对路径都基于此;
-
若Dockerfile在子目录,要COPY父目录的文件,必须把context设置为父目录,再指定dockerfile路径,示例:
services:
flask-demo:
image: flask-demo:v1.0
build:
context: . # 上下文设为compose文件所在目录
dockerfile: ./app/Dockerfile # 明确Dockerfile路径
坑3:忽略pull_policy,用latest标签导致镜像版本始终不更新
现象:远程仓库的latest镜像已经更新,但本地执行up命令始终用旧镜像,服务不更新。
错误原因:默认的missing策略,仅在本地无镜像时才会拉取,哪怕仓库有最新版本也不会更新,latest标签不会自动触发镜像拉取。
官方正确写法:
-
开发/测试环境:
pull_policy: always,始终拉取最新镜像,确保测试的是最新代码; -
生产环境:固定镜像版本号(禁止用latest),
pull_policy: missing,避免意外拉取未验证的镜像。
坑4:构建时不加--no-cache,导致代码变更不生效
现象:修改了Dockerfile和业务代码,重新执行build命令,结果服务启动后还是旧代码。
错误原因:Docker为了提升构建速度,会复用之前的构建缓存,新手修改代码后没加--no-cache参数,Docker直接复用了旧缓存,新代码没打进镜像。
官方正确命令:代码变更后,强制无缓存构建
docker compose build --no-cache flask-demo # 仅构建指定服务
docker compose up -d # 用新镜像重建容器
坑5:把敏感信息写在build.args里,导致密钥泄露
现象:把数据库密码、Git密钥写在构建参数里,结果任何人都能通过docker history命令查看到这些敏感信息,直接造成数据泄露。
错误原因:构建参数会被永久保存在镜像历史里,无任何加密,绝对不能用于传递敏感信息。
官方正确做法:
-
敏感信息用
secrets字段传递,仅在构建时临时挂载,不会保存在镜像里; -
示例:
services:
flask-demo:
build:
context: .
secrets:
- git_token # 构建时可访问的密钥
secrets:
git_token:
file: ./git_token.txt # 本地密钥文件,加入.gitignore
官方推荐最佳实践(新手直接抄)
-
开发环境:
-
pull_policy: build,仅在构建时,拉取基础镜像; -
配合绑定挂载实现代码热更新,无需重复构建镜像;
-
用
Dockerfile.dev区分开发和生产构建文件。
-
-
测试/CI环境:
-
pull_policy: always,始终拉取最新镜像,确保测试的是最新代码; -
构建时加
--no-cache,避免缓存导致的测试结果异常。
-
-
生产环境:
- 固定镜像版本标签(绝对禁止用latest),确保镜像可追溯、可回滚;
pull_policy: missing,避免意外拉取未验证的镜像;- Dockerfile使用多阶段构建,分离构建环境和运行环境,减小镜像体积,降低安全风险;
- 基础镜像替换为国内加速源(阿里云、网易云镜像),解决镜像拉取失败、拉取慢的问题。
写在最后
本文给大家讲透了 Compose 镜像构建、服务更新的官方底层逻辑,拆解了 90% 新手都会踩的 10 个致命坑,纠正了网上流传的错误用法,还给大家准备了开箱即用的生产级配置。
新手专属福利
为了帮大家更快上手 Docker,我给大家整理了专属资料,都是我自己生产环境在用、新手能直接抄的实战内容:
- 《Docker Compose 生产级最佳实践》:包含了生产部署核心原则、官方标准做法、避坑红线,零基础也能直接落地
- Docker官方维护 《10套开箱即用Compose配置文件》:覆盖Python/NGINX/MySQL等主流技术栈,可直接复制到生产环境使用
- 《Docker 实战》 全系列文章 PDF 版本,方便大家随时随地可读。
2种资料领取方式:
👉 方式一(极速领取):前往我的「公众号主页」,点击「领资料」->「联系我」,自动发放 “资料链接” + 全套福利
👉 方式二(便捷领取):私信我,发送关键词【Compose】,自动给你资料领取详情。
我会持续更新 Docker、云原生、Python 后端的实战干货,把我踩过的坑、总结的实战经验全部分享给你,帮你从入门到精通,少走弯路。
我们下期再见。
其他疑问
90% 的 Docker 新手都踩过的 8 个 Compose 坑!一文讲透核心逻辑,新手直接抄
Docker多容器环境,别瞎部署了!搞懂Compose,少走 90% 的弯路
Docker host 网络别再踩坑了!90%的新手都踩过的3 个坑+4 个网络核心要点,看完少走 90% 弯路
Docker 端口映射别瞎学了!90% 新手都栽在 -p 参数上,服务死活访问不到?看完少走 90% 弯路
Docker bridge 网络 3 个致命坑 + 官方最佳实践,新手看完少走 90% 的弯路
相关内容我都给大家做好了,感兴趣的朋友来「我的主页」找一找,直接就可以看到。
欢迎关注 「王二哥的技术笔记」,每天分享「Docker」、「Python」、「FastAPI」、「Flask」有趣干货,千万不要错过!
更多推荐




所有评论(0)