90% Docker 新手都栽在这!Compose 镜像构建的 5 个致命坑,新手直接抄

fNMBrBLrv

凌晨两点,你还在对着服务器敲命令。

改了一下午的业务代码,终于要更新到测试环境了。你信心满满敲下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,还是没搞懂buildimage两个字段的关系,这是所有构建坑的根源。

Docker官方规范明确了Compose镜像处理的核心规则:先拉取、后构建,优先级由pull_policy字段控制。

  1. image字段:定义镜像的最终名称/拉取地址,支持远程私有仓库地址,是镜像的唯一标识;
  2. build字段:定义镜像的构建规则,包含构建上下文、Dockerfile路径、构建参数等;
  3. 当一个服务同时定义了buildimage:Compose 会先按拉取策略尝试拉取镜像,若本地/仓库不存在该镜像,再按build规则构建镜像,最终将构建好的镜像打上image字段定义的标签;
  4. 若只定义了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 实战》**系列文章里。

关注 我「王二哥的技术笔记」:

  1. 查看往期全系列文章。
  2. 及时接收最新更新文章。

本文只讲了 Compose 镜像拉取和构建的核心避坑点,更深度的生产级最佳实践、全场景配置模板,我已经整理成了完整的进阶手册。

私信我,发送关键词【Compose】,即可直接领取全套资料。

坑1:只写了build没写image,导致镜像无法推送、重复构建

现象:每次执行docker compose up都要重新构建镜像,执行push命令提示警告,无法推送镜像到仓库。

错误原因:没有image字段,Compose会自动生成临时镜像名,没有固定标识,无法推送至远程仓库;且每次启动都会校验构建,无法复用本地镜像。

官方正确写法:必须同时定义buildimage字段,示例:


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

官方推荐最佳实践(新手直接抄)

  1. 开发环境

    • pull_policy: build,仅在构建时,拉取基础镜像;

    • 配合绑定挂载实现代码热更新,无需重复构建镜像;

    • Dockerfile.dev区分开发和生产构建文件。

  2. 测试/CI环境

    • pull_policy: always,始终拉取最新镜像,确保测试的是最新代码;

    • 构建时加--no-cache,避免缓存导致的测试结果异常。

  3. 生产环境

    • 固定镜像版本标签(绝对禁止用latest),确保镜像可追溯、可回滚;
    • pull_policy: missing,避免意外拉取未验证的镜像;
    • Dockerfile使用多阶段构建,分离构建环境和运行环境,减小镜像体积,降低安全风险;
    • 基础镜像替换为国内加速源(阿里云、网易云镜像),解决镜像拉取失败、拉取慢的问题。

写在最后

本文给大家讲透了 Compose 镜像构建、服务更新的官方底层逻辑,拆解了 90% 新手都会踩的 10 个致命坑,纠正了网上流传的错误用法,还给大家准备了开箱即用的生产级配置。

新手专属福利

为了帮大家更快上手 Docker,我给大家整理了专属资料,都是我自己生产环境在用、新手能直接抄的实战内容:

  1. 《Docker Compose 生产级最佳实践》:包含了生产部署核心原则、官方标准做法、避坑红线,零基础也能直接落地
  2. Docker官方维护 《10套开箱即用Compose配置文件》:覆盖Python/NGINX/MySQL等主流技术栈,可直接复制到生产环境使用
  3. 《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」有趣干货,千万不要错过!

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐