必须显式写死 image 字段的标签或 digest,否则默认使用 :latest 导致版本不可控;image: nginx 等价于 nginx:latest(移动靶),而 image: nginx:1.25.4 或 nginx@sha256:abc123... 才能确保内容可验证、可复现。

必须显式写死 image 字段的标签(tag),否则默认用 :latest,根本不可控。 Docker Desktop 本身不提供“镜像版本固定开关”,所有版本控制逻辑都在 docker-compose.yml 文件里,靠你手动写对、写全、写稳。
为什么 image: nginx 不等于固定版本
这是最常踩的坑:省略 tag 时,Docker 默认解析为 nginx:latest。而 :latest 是个移动靶——今天拉的是 1.25,明天仓库更新后可能就变成 1.26,甚至 ABI 不兼容。本地跑通、CI 失败、上线报错,八成出在这儿。
-
image: nginx→ 实际拉取nginx:latest,每次docker compose up都可能变 -
image: nginx:1.25.4→ 拉取确定 digest 的镜像,内容可验证、可复现 -
image: nginx@sha256:abc123...→ 最严格,跳过 tag,直连镜像 digest,彻底规避 tag 被覆盖风险
image 字段支持的三种写法及适用场景
不是所有写法都适合生产环境,得看你要什么级别的确定性:
-
image: redis:7.2.5-alpine:适合开发/测试,依赖官方语义化版本,但需信任镜像维护者不篡改 tag -
image: redis@sha256:9f8a6c932b1d4e0f3e1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4:生产必备,docker inspect查到的RepoDigests值,哪怕 tag 被重推也纹丝不动 -
image: my-registry.example.com/app:20261023-v1.2.0:私有 registry 场景,用时间戳+语义版本组合,便于回溯和灰度
别信 build: 就安全——它也可能偷偷变
用 build: 构建本地镜像,不代表版本就稳了。如果 Dockerfile 里写了 FROM ubuntu:latest 或 pip install flask,构建结果照样漂移。
- 检查
Dockerfile中所有FROM行,确保带明确 tag 或 digest,例如FROM python:3.11-slim-bookworm - 构建时加
--no-cache并记录输出中的Successfully built abc123,这个 ID 才是本次构建的真实标识 - 想让
build:服务也带可追溯标签?在docker-compose.yml里补上image:字段:services: api: build: . image: my-api:20261023-abc123然后docker compose push推到 registry,后续部署才真正可控
Compose 自动加的标签(com.docker.compose.image)不能当版本依据
虽然 docker compose ps 看到容器 labels 里有 com.docker.compose.image: "sha256:...",但它只是 Compose 启动时“当时”记录的镜像 digest,不反映你是否真的用了这个 digest 启动——比如你改了 image: 但没 pull,它还是旧值;或者你 pull 了新镜像但没 up --force-recreate,它也不会更新。
真正可靠的版本锚点,只有你亲手写进 docker-compose.yml 的 image: 字段,且必须含 tag 或 digest。其他都是快照、是线索、是辅助排查用的,不是契约。











