15.11.5 镜像与仓库问题处理
镜像与仓库问题处理覆盖“构建—分发—拉取—使用”的全链路故障定位与修复。处理原则是先缩小范围(构建端/客户端/仓库端/网络与权限),再验证配置与日志,最后通过最小化复现与灰度修复降低影响。以下内容包含原理草图、命令示例、安装与排错步骤,以及练习。
常见问题与定位路径#
构建失败:基础镜像不可达、Dockerfile语法错误、依赖下载失败、上下文过大或缓存污染。
体积异常:未清理缓存、重复安装、将敏感文件打入镜像。
推送/拉取失败:denied、unauthorized、connection reset、manifest 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
故障处理流程(可落地)#
- 复现错误:保留完整错误信息与命令。
- 分层定位:构建端 vs 客户端 vs 仓库端。
- 网络与证书:DNS、代理、TLS、端口连通性。
- 仓库健康:Registry日志、存储后端容量与健康。
- 最小化验证:最小 Dockerfile + 临时镜像标签。
- 回滚策略:启用 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"
预期:无论标签是否变更,拉取内容不变。