Skip to content

Docker 镜像拉取折腾记录

🕒 Published at:

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,解压阶段无响应。

根因排查 ​

  1. 关掉 snapshotter(切回 overlay2)→ SRS 正常拉取
  2. 但切换后其他镜像全丢(存储目录不兼容)
  3. 切回 snapshotter=true → SRS 又卡死
  4. 清理 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

关键教训 ​

  1. Docker daemon != 你的终端,代理要单独配(systemd override),daemon.json 里的 proxies 字段只管 client(docker build),不管 daemon 拉镜像
  2. containerd-snapshotter 不能来回切换,两个驱动用不同存储目录,切一次丢一次镜像
  3. 国内镜像源不全,有些镜像的层找不到,需要纯走代理拉
  4. 失败的 pull 要清理残留,否则阻塞后续 pull
  5. overlay2 在 snapshotter=true 模式下是孤儿数据,可以安全删除
  6. 先确认存储驱动,再拉镜像,别中途换

相关文件 ​

文件作用
/etc/docker/daemon.jsonDocker 配置(镜像源 + snapshotter)
/etc/systemd/system/docker.service.d/proxy.confdaemon 代理
/var/lib/docker/Docker 总存储目录
/var/lib/containerd/containerd 内容存储(snapshotter=true 时)
/var/lib/docker/overlay2/overlay2 存储(snapshotter=false 时用,true 时为空)