15.11.5 镜像与仓库问题处理

镜像与仓库问题处理覆盖“构建—分发—拉取—使用”的全链路故障定位与修复。处理原则是先缩小范围(构建端/客户端/仓库端/网络与权限),再验证配置与日志,最后通过最小化复现与灰度修复降低影响。以下内容包含原理草图、命令示例、安装与排错步骤,以及练习。

文章图片

常见问题与定位路径#

构建失败:基础镜像不可达、Dockerfile语法错误、依赖下载失败、上下文过大或缓存污染。
体积异常:未清理缓存、重复安装、将敏感文件打入镜像。
推送/拉取失败deniedunauthorizedconnection resetmanifest unknown
仓库不可用:Registry进程异常、存储后端故障、证书过期、限流超时。
签名/完整性:内容信任开启但未签名,digest漂移。


安装与基础环境(示例:私有 Registry)#

# 1) 拉起官方 registry
docker run -d --name registry \
  -p 5000:5000 \
  -v /opt/registry/data:/var/lib/registry \
  -v /opt/registry/config:/etc/docker/registry \
  registry:2

# 2) 验证健康
curl -sS http://127.0.0.1:5000/v2/_catalog
# 预期:返回 {"repositories":[]} 或已有仓库列表

若使用 HTTPS,需要证书并配置 Docker 端信任:

# 服务器端:准备证书
mkdir -p /opt/registry/certs
# 省略证书生成过程,放置 registry.crt 与 registry.key

# 服务器端启动(示例)
docker run -d --name registry \
  -p 5000:5000 \
  -v /opt/registry/data:/var/lib/registry \
  -v /opt/registry/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
  registry:2

# 客户端:信任证书
sudo mkdir -p /etc/docker/certs.d/registry.local:5000
sudo cp /path/registry.crt /etc/docker/certs.d/registry.local:5000/ca.crt
sudo systemctl restart docker

典型故障场景与排查示例#

1) 构建失败:基础镜像不可达/上下文过大#

# 1) 观察构建日志
docker build --progress=plain -t demo:1.0 .

# 2) 检查 DNS/代理
cat /etc/resolv.conf
env | grep -i proxy

# 3) 检查上下文大小
du -sh .
cat .dockerignore

# 4) 最小化 Dockerfile 测试
cat > /tmp/Dockerfile.min <<'EOF'
FROM alpine:3.18
RUN echo ok
EOF
docker build -f /tmp/Dockerfile.min -t min:1.0 /tmp

解释--progress=plain输出详细日志;/tmp/Dockerfile.min用于验证基础镜像和构建引擎是否正常。

2) 镜像体积异常膨胀#

# 多阶段构建示例(修复体积问题)
FROM golang:1.20 AS builder
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o app .

FROM alpine:3.18
RUN adduser -D appuser
COPY --from=builder /src/app /app
USER appuser
ENTRYPOINT ["/app"]

解释:构建产物与运行环境分离,避免把编译缓存与源码打入最终镜像。

3) 推送/拉取失败:权限与标签#

# 1) 登录仓库
docker login registry.local:5000

# 2) 重新打标签并推送
docker tag demo:1.0 registry.local:5000/team/demo:1.0
docker push registry.local:5000/team/demo:1.0

# 3) 拉取并验证
docker pull registry.local:5000/team/demo:1.0
docker images | grep demo

常见错误解释
- denied/unauthorized:凭据或权限不足;确认账号有 push/pull 权限。
- manifest unknown:标签不存在或被清理;检查仓库标签列表。

4) manifest unknown 排查(仓库端)#

# 1) 查询仓库目录
curl -sS http://registry.local:5000/v2/_catalog

# 2) 查询标签列表
curl -sS http://registry.local:5000/v2/team/demo/tags/list

# 3) 若无标签,重新推送或修复清理策略

5) 证书与 TLS 问题#

# 客户端测试证书
openssl s_client -connect registry.local:5000 -showcerts

# 查看 Docker 端日志(关键字 TLS)
journalctl -u docker | tail -n 50

解释:证书链不完整或主机名不匹配会导致 x509 相关错误。


关键命令速查(含解释)#

# 构建:显示详细过程
docker build --progress=plain -t app:1.0 .

# 查看镜像层与体积
docker history app:1.0

# 清理构建缓存(谨慎)
docker builder prune

# 获取镜像 digest,避免标签漂移
docker inspect --format='{{index .RepoDigests 0}}' app:1.0

# 以 digest 拉取,确保一致性
docker pull registry.local:5000/team/demo@sha256:xxxx

# 查看仓库端容器日志
docker logs registry | tail -n 100

故障处理流程(可落地)#

  1. 复现错误:保留完整错误信息与命令。
  2. 分层定位:构建端 vs 客户端 vs 仓库端。
  3. 网络与证书:DNS、代理、TLS、端口连通性。
  4. 仓库健康:Registry日志、存储后端容量与健康。
  5. 最小化验证:最小 Dockerfile + 临时镜像标签。
  6. 回滚策略:启用 digest 拉取、备用仓库、预热镜像。

练习(含预期效果)#

1) 构建最小镜像并推送

cat > /tmp/Dockerfile <<'EOF'
FROM alpine:3.18
RUN echo "hello" > /msg.txt
CMD ["cat", "/msg.txt"]
EOF

docker build -t hello:1.0 /tmp
docker tag hello:1.0 registry.local:5000/lab/hello:1.0
docker push registry.local:5000/lab/hello:1.0

预期:仓库中出现 lab/hello,拉取后运行输出 hello

2) 模拟 manifest unknown

docker pull registry.local:5000/lab/hello:9.9

预期:出现 manifest unknown,随后通过 tags/list 验证仅有 1.0

3) 验证 digest 拉取一致性

DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' registry.local:5000/lab/hello:1.0)
docker pull "$DIGEST"

预期:无论标签是否变更,拉取内容不变。