Docker 29.7.1 是一次针对回归问题的修复版本。此次公开摘要点出了两个容易影响构建和部署流水线的问题:部分结构特殊的镜像无法拉取,以及 CopyToContainer 无法正确处理容器路径中的绝对符号链接。它们都不是新功能,却可能直接导致原本稳定的自动化任务突然失败。
镜像图层中的隐式父目录可以再次正常处理
第一个修复针对镜像拉取回归:当图层包含某个目录,但归档中没有为它的父目录提供明确条目时,Docker 可能拒绝拉取该镜像。
容器镜像的文件系统由多个图层叠加而成。图层归档不一定显式列出每一级父目录,例如归档可能包含:
opt/example/bin/server
但没有单独包含:
opt/
opt/example/
opt/example/bin/
这类归档结构并不罕见,尤其是镜像由不同构建器、导入工具或归档流程生成时。Docker 29.7.1 修复了相关回归,使这类镜像能够再次被拉取。
升级后,可以用此前失败的实际镜像执行一次强制拉取验证。将 IMAGE 改成受影响的完整镜像引用:
#!/usr/bin/env bash
set -euo pipefail
IMAGE="registry.example.com/team/app:release-tag"
docker version --format 'Client: {{.Client.Version}} | Server: {{.Server.Version}}'
docker image rm "$IMAGE" 2>/dev/null || true
docker pull "$IMAGE"
docker image inspect "$IMAGE" --format 'ID={{.Id}} Layers={{len .RootFS.Layers}}'
删除本地镜像是为了避免缓存掩盖拉取问题。不要在仍依赖该镜像的生产节点上直接执行删除操作,建议先在隔离的测试主机或临时 CI Runner 上验证。
CopyToContainer 恢复遍历绝对符号链接
另一个修复涉及向容器复制文件的路径解析。此前的回归会导致 CopyToContainer 拒绝遍历绝对符号链接,例如:
/var/run -> /run
这种目录布局很常见。调用 Docker API 的 SDK、部署脚本和部分开发工具可能通过 CopyToContainer 向 /var/run/... 写入文件;即使最终目标位于容器内部,回归版本也可能在解析绝对符号链接时拒绝操作。
命令行中的 docker cp 会走相关的容器归档复制能力,因此可以用它做一个小型验收测试:
#!/usr/bin/env bash
set -euo pipefail
container="docker-2971-copy-test"
tmpfile="$(mktemp)"
trap 'rm -f "$tmpfile"; docker rm -f "$container" >/dev/null 2>&1 || true' EXIT
printf 'docker-copy-test\n' > "$tmpfile"
docker run -d --name "$container" alpine:3.20 sleep 300
docker exec "$container" sh -c 'mkdir -p /run && rm -rf /var/run && ln -s /run /var/run'
docker cp "$tmpfile" "$container:/var/run/copied.txt"
docker exec "$container" sh -c 'test "$(cat /run/copied.txt)" = "docker-copy-test"'
printf 'Copy through /var/run -> /run succeeded.\n'
运行前需要本机 Docker 守护进程可用,并允许拉取 alpine:3.20。脚本会创建临时容器、建立绝对符号链接,然后通过 /var/run 写入文件并从真实目标 /run 校验内容。
升级时不要只看客户端版本
这两个问题都位于 Docker Engine 处理镜像或容器文件系统的路径上。验证升级是否生效时,应同时检查客户端与服务端版本:
docker version --format $'Client={{.Client.Version}}\nServer={{.Server.Version}}'
如果客户端已经是 29.7.1,但服务端仍是旧版本,远程 Docker 主机、Docker-in-Docker 服务或 CI Runner 仍可能保留原有行为。对于通过 SDK 调用 CopyToContainer 的应用,也应确认其连接的实际守护进程版本,而不只是应用镜像中安装的 Docker CLI 版本。
建议的落地检查
升级可以围绕真实失败场景进行,而不是只确认服务能够启动:
- 在测试环境升级 Docker Engine,并确认服务端版本为 29.7.1。
- 清除测试节点上的目标镜像缓存,重新拉取此前受影响的镜像。
- 对依赖
/var/run -> /run等绝对符号链接的复制流程执行回归测试。 - 检查 CI Runner、远程构建节点和 Docker-in-Docker 服务,避免只升级开发机。
- 保留升级前的守护进程配置与回滚方案,并结合完整发布说明评估摘要未列出的其他变化。
Docker 29.7.1 的价值在于恢复兼容行为。若团队已经遇到镜像拉取异常,或工具链依赖向符号链接路径复制文件,这一版本应优先进入验证队列;如果尚未遇到问题,也应按照常规补丁升级流程逐步推广,避免跳过针对真实镜像和复制路径的验收。