问题现象
执行 docker build 构建镜像时,无法从私有 Harbor 仓库拉取基础镜像:
ERROR: failed to solve: 192.168.x.x:80/infra/alpine:3.23.2:
failed to resolve source metadata: failed to do request:
Head "https://192.168.x.x:80/v2/infra/alpine/manifests/3.23.2": EOF
尝试 docker login 同样失败:
Error response from daemon: Get "http://192.168.x.x:80/v2/": EOF
环境信息
- Docker Desktop for Windows (WSL2 backend)
- 私有 Harbor 仓库,HTTP 协议(非 HTTPS)
- 已配置 Insecure Registries
排查过程
Step 1: 验证网络连通性
ping 192.168.x.x
# 结果: 正常响应,网络可达
Step 2: 验证 Registry 服务状态
curl -v http://192.168.x.x:80/v2/
返回结果:
HTTP/1.1 401 Unauthorized
Docker-Distribution-Api-Version: registry/2.0
Www-Authenticate: Bearer realm="http://192.168.x.x/service/token"
{"errors":[{"code":"UNAUTHORIZED","message":"unauthorized"}]}
关键发现: Registry 服务正常运行,返回 401 表示需要认证,这是预期行为。
Step 3: 检查 Docker 配置
docker info
确认 Insecure Registries 配置:
Insecure Registries:
192.168.x.x:80
127.0.0.0/8
配置正确,排除 HTTP/HTTPS 协议问题。
Step 4: 定位根因
继续检查 docker info 输出,发现代理配置:
HTTP Proxy: http.docker.internal:3128
HTTPS Proxy: http.docker.internal:3128
No Proxy: hubproxy.docker.internal
根因确认: Docker Desktop 配置了代理,但私有仓库地址未加入 No Proxy 列表,导致请求被代理拦截后返回 EOF。
解决方案
方法一:添加 No Proxy 例外(推荐)
- 打开 Docker Desktop → Settings
- 进入 Resources → Proxies
- 在 Bypass proxy settings for these hosts & domains 添加私有仓库地址
- Apply & Restart
方法二:临时禁用代理
如果不需要代理,可直接关闭 Manual proxy configuration。
验证修复
# 登录测试
docker login 192.168.x.x:80
# 构建测试
docker build -f deployments/Dockerfile -t your-image:tag .
总结
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| EOF 错误 | 代理拦截 | 检查 docker info 中的 Proxy 配置 |
| EOF 错误 | 网络不通 | ping / curl 测试连通性 |
| 401 Unauthorized | 认证问题 | 正常现象,需要 docker login |
| HTTPS 证书错误 | 未配置 Insecure Registry | 检查 docker info 中的 Insecure Registries |
核心经验: 当 curl 能正常访问但 Docker 客户端返回 EOF 时,优先排查代理配置。
附录:构建阶段网络问题
问题现象
Registry 连接问题解决后,构建过程中 apk add 失败:
WARNING: fetching https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/APKINDEX.tar.gz: Connection refused
ERROR: unable to select packages:
ca-certificates (no such package)
原因分析
Docker Desktop 的代理配置影响容器内部网络。即使宿主机能访问外网,容器内的请求仍被代理拦截。
解决方案
方案一:关闭代理
Docker Desktop → Settings → Resources → Proxies → 关闭 Manual proxy configuration
方案二:优化 Dockerfile(推荐)
避免在构建时访问外网,利用基础镜像已有的资源:
# 原始写法(需要网络)
RUN apk --no-cache add ca-certificates tzdata
# 优化写法(无需网络)
# 基础镜像已包含 ca-certificates,时区通过环境变量设置
ENV TZ=Asia/Shanghai
如果代码使用 time.LoadLocation(),需要内嵌时区数据:
import _ "time/tzdata" // Go 1.15+ 内嵌时区数据
最终 Dockerfile
FROM registry/golang:1.25-alpine AS builder
WORKDIR /app
ENV GOPROXY=https://goproxy.cn,direct
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags='-s -w' -o /api ./cmd/api
FROM registry/alpine:3.23.2
ENV TZ=Asia/Shanghai
WORKDIR /app
COPY --from=builder /api /app/api
COPY configs/config.prod.yaml /app/configs/config.yaml
EXPOSE 8080
ENTRYPOINT ["/app/api"]
附录总结
| 问题 | 解决方案 |
|---|---|
| apk 无法访问外网 | 关闭代理 或 避免构建时下载 |
| 需要 ca-certificates | 使用已包含证书的基础镜像 |
| 需要时区数据 | ENV TZ=xxx 或 Go 内嵌 time/tzdata |