Docker 29.7.1 修复镜像拉取与绝对符号链接复制回归

2026-08-03 39 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:7 分钟

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 版本。

建议的落地检查

升级可以围绕真实失败场景进行,而不是只确认服务能够启动:

  1. 在测试环境升级 Docker Engine,并确认服务端版本为 29.7.1。
  2. 清除测试节点上的目标镜像缓存,重新拉取此前受影响的镜像。
  3. 对依赖 /var/run -> /run 等绝对符号链接的复制流程执行回归测试。
  4. 检查 CI Runner、远程构建节点和 Docker-in-Docker 服务,避免只升级开发机。
  5. 保留升级前的守护进程配置与回滚方案,并结合完整发布说明评估摘要未列出的其他变化。

Docker 29.7.1 的价值在于恢复兼容行为。若团队已经遇到镜像拉取异常,或工具链依赖向符号链接路径复制文件,这一版本应优先进入验证队列;如果尚未遇到问题,也应按照常规补丁升级流程逐步推广,避免跳过针对真实镜像和复制路径的验收。


相关推荐