Docker 镜像拉取折腾记录
日期: 2026-08-11
环境
- Docker: 26.1.5+dfsg1
- 内核: 6.12.95
- 存储驱动: overlayfs + containerd-snapshotter(最终方案)
- 网络: 需走代理
http://192.168.31.82:7890 - 镜像源:
https://docker.1ms.run
问题 1: Docker daemon 没走代理
终端 .bashrc 里有 export http_proxy=...,但 Docker daemon 是 systemd 启动的,不继承你的 shell 环境变量。所以 docker pull 直连 Docker Hub,连不上,下载卡死。
解决: systemd override
bash
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/proxy.conf <<'EOF'
[Service]
Environment="HTTP_PROXY=http://192.168.31.82:7890"
Environment="HTTPS_PROXY=http://192.168.31.82:7890"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker问题 2: containerd-snapshotter 与 overlay2 的坑
背景
Docker 26.x 有两个存储驱动模式:
containerd-snapshotter=false(默认):用 overlay2,Docker 自己管解压containerd-snapshotter=true:用 overlayfs,containerd 管解压
两个模式的存储目录互不兼容,不能来回切换。
现象
开启 snapshotter=true 后,pgvector/redis/minio/traefik 全部拉取成功。但拉 SRS(ossrs/srs:6)时卡死——下载完所有 layer,解压阶段无响应。
根因排查
- 关掉 snapshotter(切回 overlay2)→ SRS 正常拉取
- 但切换后其他镜像全丢(存储目录不兼容)
- 切回 snapshotter=true → SRS 又卡死
- 清理 containerd 残留数据 + 重启 → SRS 拉取成功
最终结论: SRS 卡死是因为之前失败 pull 留下的 containerd 残留数据。清干净后 snapshotter=true 下 SRS 也能正常拉取。
教训
绝对不要在两种存储驱动之间来回切换。 一旦选定了,就一直用那个。
问题 3: 镜像源没有某些镜像的层
docker.1ms.run 国内镜像源不是所有镜像都有。SRS 的层在镜像源上找不到,导致下载一直 Retrying。
解决: 去掉 registry-mirrors,纯走代理拉取。
bash
# 临时去掉镜像源
sudo tee /etc/docker/daemon.json <<'EOF'
{
"features": {
"containerd-snapshotter": true
}
}
EOF
sudo systemctl restart docker
docker pull ossrs/srs:6
# 拉完后恢复镜像源问题 4: overlay2 残留垃圾
在 snapshotter=false 期间拉取的 SRS 镜像,层数据存在 /var/lib/docker/overlay2/。切回 snapshotter=true 后,这些数据变成孤儿,占用 169MB。
清理: 停 Docker → 删 overlay2 → 重启
bash
sudo systemctl stop docker.socket docker.service
sudo rm -rf /var/lib/docker/overlay2
sudo mkdir -p /var/lib/docker/overlay2
sudo chmod 700 /var/lib/docker/overlay2
sudo systemctl start docker.service问题 5: containerd 残留脏数据阻塞 pull
失败的 pull 会在 containerd 内容存储里留下半成品数据,新 pull 时卡在解压上。
清理: 停服务 → 清 snapshotter 目录 → 重启
bash
sudo systemctl stop docker.socket docker.service containerd.service
sudo rm -rf /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/*
sudo systemctl start containerd.service
sleep 2
sudo systemctl start docker.service最终配置
json
// /etc/docker/daemon.json
{
"features": {
"containerd-snapshotter": true
},
"registry-mirrors": ["https://docker.1ms.run"]
}ini
// /etc/systemd/system/docker.service.d/proxy.conf
[Service]
Environment="HTTP_PROXY=http://192.168.31.82:7890"
Environment="HTTPS_PROXY=http://192.168.31.82:7890"
Environment="NO_PROXY=localhost,127.0.0.1"最终拉取的镜像
bash
docker pull pgvector/pgvector:pg16 # 621MB
docker pull redis:7-alpine # 57.3MB
docker pull minio/minio # 241MB
docker pull traefik:v3.3 # 285MB
docker pull ossrs/srs:6 # 227MB关键教训
- Docker daemon != 你的终端,代理要单独配(systemd override),daemon.json 里的
proxies字段只管 client(docker build),不管 daemon 拉镜像 - containerd-snapshotter 不能来回切换,两个驱动用不同存储目录,切一次丢一次镜像
- 国内镜像源不全,有些镜像的层找不到,需要纯走代理拉
- 失败的 pull 要清理残留,否则阻塞后续 pull
- overlay2 在 snapshotter=true 模式下是孤儿数据,可以安全删除
- 先确认存储驱动,再拉镜像,别中途换
相关文件
| 文件 | 作用 |
|---|---|
/etc/docker/daemon.json | Docker 配置(镜像源 + snapshotter) |
/etc/systemd/system/docker.service.d/proxy.conf | daemon 代理 |
/var/lib/docker/ | Docker 总存储目录 |
/var/lib/containerd/ | containerd 内容存储(snapshotter=true 时) |
/var/lib/docker/overlay2/ | overlay2 存储(snapshotter=false 时用,true 时为空) |