主题
拉不到镜像怎么办
国内家用网络下 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 timeoutregistry-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 Hub | docker.m.daocloud.io | 响应快(~0.1s),首选 |
| Docker Hub | docker.1panel.live | 备选 |
| Docker Hub | docker.1ms.run | 备选 |
| ghcr.io | ghcr.nju.edu.cn | 实测无白名单限制 |
| ghcr.io | ghcr.m.daocloud.io | ❌ 有白名单,不在名单的镜像报 not in the allowlist |
公共镜像代理本质是别人在替你付带宽,所以:
- 不要往里推镜像(多数不支持 push)
- 镜像可能是几天前的缓存,
latest标签尤其容易落后。拉完用 digest 或创建时间确认一下:bashdocker inspect --format '{{.Created}}' redis:7-alpine
排查顺序(记下来省时间)
- 看错误是超时还是 401/403
- 超时 → 网络问题,换源或走代理
- 401 → 源要认证(多半是厂商内部源),换公共代理源
- 403 +
not in the allowlist→ 这个代理有白名单,换一个
- 测源本身通不通,别一上来就重启 docker:bash
curl -s -o /dev/null -w '%{http_code} %{time_total}s\n' https://docker.m.daocloud.io/v2/ - 区分"镜像不存在"和"源不可用":
manifest unknown是镜像名/tag 错了,跟网络无关 - 别忘
library/前缀 —— 这个错误最像"镜像不存在",最容易白折腾
一句话版本:Docker Hub 的坑用前缀代理解决,ghcr 的坑用
ghcr.nju.edu.cn解决,厂商自带加速源大概率不给你用。