Skip to content

拉不到镜像怎么办 ​

国内家用网络下 docker pull 失败是常态,不是你的问题。但"加个加速源"这件事,坑比想象的多 —— 尤其是 NAS 自带的那个加速源,看着配好了,实际上只给自家应用中心用。

现象 ​

bash
$ docker pull redis:7-alpine
Error response from daemon: Get "https://registry-1.docker.io/v2/":
  dial tcp 44.208.x.x:443: i/o timeout

registry-1.docker.io 超时。看 daemon 配置,registry-mirrors 里明明有一个厂商自带的加速地址:

json
{
  "registry-mirrors": ["docker.fnnas.com", "registry.hub.docker.com"]
}

但用它拉公共镜像会返回 401 —— 那个源只服务应用中心里分发的镜像,匿名拉公共镜像没权限。

三个思路,按侵入性排序 ​

方案 A:临时指定镜像源拉取,再打回原名(推荐先用这个) ​

不改任何配置,直接在命令里指定代理源,拉到本地后 docker tag 改回原名:

bash
# Docker Hub 官方镜像 —— 注意要加 library/ 前缀
docker pull docker.m.daocloud.io/library/redis:7-alpine
docker tag  docker.m.daocloud.io/library/redis:7-alpine redis:7-alpine

# 带命名空间的镜像,前缀照加
docker pull docker.m.daocloud.io/linuxserver/ffmpeg:latest
docker tag  docker.m.daocloud.io/linuxserver/ffmpeg:latest linuxserver/ffmpeg:latest

# ghcr.io 上的镜像
docker pull ghcr.nju.edu.cn/toeverything/affine:stable
docker tag  ghcr.nju.edu.cn/toeverything/affine:stable ghcr.io/toeverything/affine:stable

要点:

  • 官方镜像必须加 library/,因为 Docker Hub 上 redis 的完整路径是 library/redis
  • docker tag 之后,docker-compose.yml 里原来写 image: redis:7-alpine 也能直接跑,不用改文件
  • 但要注意:docker compose pull 还是会去找原始 registry。所以升级镜像时也要用这个方式拉,不能指望 compose 自己处理

方案 B:写进 daemon.json 的 registry-mirrors ​

一劳永逸,但要重启 dockerd:

json
{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://docker.1panel.live",
    "https://docker.fnnas.com"
  ]
}
bash
sudo systemctl restart docker

如果 daemon 开了 live-restore: true,重启 dockerd 不会重启容器(服务不中断),这是推荐开着的配置:

json
{
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": { "max-size": "100m", "max-file": "5" }
}

注意 registry-mirrors 只能代理 Docker Hub。ghcr.io、quay.io、gcr.io 这些不在范围内,还是得用方案 A 的前缀写法。

方案 C:整机走代理 ​

如果机器上已经有 HTTP 代理(比如 Clash 之类的本地代理端口),可以给 dockerd 配 systemd drop-in:

ini
# /etc/systemd/system/docker.service.d/proxy.conf
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,::1"
bash
sudo systemctl daemon-reload && sudo systemctl restart docker

⚠️ 几个注意点:

  • NO_PROXY 一定要写,否则容器访问 localhost 上的服务会绕去代理
  • dockerd 跑在 127.0.0.1:7890 的代理时,容器内的流量不一定走代理(取决于网络模式),别指望这样就能让容器内也翻墙
  • 代理不稳的时候,拉镜像会莫名其妙地挂住,排查的时候容易误判成"镜像源坏了"

实测可用的源(某次测试记录,随时可能失效) ​

用途地址备注
Docker Hubdocker.m.daocloud.io响应快(~0.1s),首选
Docker Hubdocker.1panel.live备选
Docker Hubdocker.1ms.run备选
ghcr.ioghcr.nju.edu.cn实测无白名单限制
ghcr.ioghcr.m.daocloud.io❌ 有白名单,不在名单的镜像报 not in the allowlist

公共镜像代理本质是别人在替你付带宽,所以:

  • 不要往里推镜像(多数不支持 push)
  • 镜像可能是几天前的缓存,latest 标签尤其容易落后。拉完用 digest 或创建时间确认一下:
    bash
    docker inspect --format '{{.Created}}' redis:7-alpine

排查顺序(记下来省时间) ​

  1. 看错误是超时还是 401/403
    • 超时 → 网络问题,换源或走代理
    • 401 → 源要认证(多半是厂商内部源),换公共代理源
    • 403 + not in the allowlist → 这个代理有白名单,换一个
  2. 测源本身通不通,别一上来就重启 docker:
    bash
    curl -s -o /dev/null -w '%{http_code} %{time_total}s\n' https://docker.m.daocloud.io/v2/
  3. 区分"镜像不存在"和"源不可用":manifest unknown 是镜像名/tag 错了,跟网络无关
  4. 别忘 library/ 前缀 —— 这个错误最像"镜像不存在",最容易白折腾

一句话版本:Docker Hub 的坑用前缀代理解决,ghcr 的坑用 ghcr.nju.edu.cn 解决,厂商自带加速源大概率不给你用。