在测试机上敲 docker pull nginx,终端停在 Pulling from library/nginx 一动不动,四分钟后抛出 net/http: TLS handshake timeout。镜像没落地,后面的 docker run 自然起不来。

pull 后面把仓库名和 tag 写全

只写 nginx 时,Docker 会去 Docker Hub 的 library 命名空间找最新版。生产环境别用 latest,tag 固定住,回滚时才知道自己拉的是哪一份。

docker pull nginx:1.25

拉完先 docker image inspect 看 Architecture 和 Entrypoint。宿主机是 arm 而镜像只有 amd64,跑起来就是 exec format error,这类问题在拉取阶段看不出,得查镜像详情。

握手超时先看链路,别急着换加速地址

多数超时跟账号无关。在机器上 curl 一下 registry 地址,返回 401 说明网络通了,只是没带凭证;直接连不上或者卡住,才是出口被挡。

curl -I https://registry-1.docker.io/v2/

机器走公司代理时,只在 shell 里 export HTTP_PROXY 对 dockerd 无效,它读的是 systemd 的配置。改完要 daemon-reload 再 restart docker,不然 pull 依旧在直连。

systemctl show docker --property=Environment

这条能看到 docker 启动时到底带了哪些环境变量。里面没有代理,说明配置压根没生效,别在客户端那边反复试。

内网机器用 save 和 load 搬镜像

出不了外网的机器,就在能上网的机器上拉好、导出 tar、拷过去导入。save 带的是镜像层,容器里写入的数据不在里面。

docker save -o nginx125.tar nginx:1.25
docker load -i nginx125.tar

走私有仓库时地址要写全,形如 harbor.local/base/nginx:1.25,少一段项目名就报 repository does not exist。docker login 成功只代表凭证对了,推拉权限还得仓库那边单独给。

我的做法是:临时调试用官方地址配代理,团队一天几十次构建就搭内网 registry 做缓存层,稳定性比追着换加速地址靠谱得多。