问题背景

在中国大陆的云服务器上,由于GFW的限制,直接访问 Docker Hub (docker.io,docker.io是Docker Hub 的域名,它是 Docker 官方的镜像仓库和服务平台) 通常会遇到连接超时的问题,导致无法顺利下载 Docker 镜像 (docker pull)。

  1. docker run 的行为: 运行 docker run 命令时,如果 Docker Daemon 在本地没有找到指定的镜像(前提,通过完整的镜像名称包括仓库地址和标签),那么它会自动先执行一次 docker pull 操作来下载这个待使用的镜像,然后再创建并运行容器。所以docker run 命令本身并不是用来下载镜像的(docker pull 才是),它只是在需要时会触发下载。

  2. ghcr.nju.edu.cn/open-webui/open-webui:main 的含义: 这个字符串是一个完整的镜像名称,它遵循了 Docker 镜像命名的一种标准格式: [仓库地址[:端口(可选)]]镜像名称[:标签]

    • ghcr.nju.edu.cn: 这就是指定的仓库(Registry)地址ghcr.nju.edu.cn 是南京大学提供的 GitHub Container Registry 的镜像服务地址。
    • /open-webui/open-webui: 这是镜像的名称。在某些仓库中,镜像名称可能包含路径(如 open-webui 用户或组织下的 open-webui 仓库)。
    • :main: 这是**镜像的标签 (Tag)**,用来指定镜像的具体版本。

    当运行 docker run ... ghcr.nju.edu.cn/open-webui/open-webui:main 时,确实指定了 Docker 去 ghcr.nju.edu.cn 这个地址寻找 open-webui/open-webui:main 这个镜像。如果本地还没有这个镜像,它就会去这个仓库那里拉取。

  3. 为什么直接 docker pull 好像不能这样指定地址? 实际上,docker pull 是可以这样指定仓库地址的

    • 当运行 docker pull ubuntu 时,由于没有指定仓库地址,Docker 默认会去官方的 Docker Hub (docker.io) 查找 library/ubuntu 镜像(library 是 Docker Hub 官方镜像的默认命名空间)。这等同于运行 docker pull docker.io/library/ubuntu
    • 当运行 docker pull ghcr.nju.edu.cn/open-webui/open-webui:main 时,就是指定了仓库地址 ghcr.nju.edu.cn,Docker 就会去这个地址拉取镜像。这个命令是有效的,和用于 docker run 的镜像名称是同一个原理。

之前遇到的困惑,是因为讨论的是如何使用镜像加速器来拉取 Docker Hub 上的镜像

  • 镜像加速器 (Registry Mirror) 的作用是,当尝试拉取 docker.io 上的镜像时,Docker Daemon 会把这个请求重定向到所配置的加速器地址,让加速器代替我去 Docker Hub 下载。
  • 这种重定向机制是 Docker Daemon 的功能,通过修改 服务器的/etc/docker/daemon.json 或 Daemon 启动参数来配置。它不是 docker pull 命令的一个参数。
  • 当配置了镜像加速器之后,再拉取 Docker Hub 的 ubuntu 镜像时,仍然输入 docker pull ubuntu,但 Daemon 会在后台会使用加速器去下载。不能输入 docker pull --registry-mirror=xxx ubuntudocker pull xxx/ubuntu (除非加速器把镜像放在这样的路径下)。

总结一下:

  • docker run 在镜像不存在时会先执行 docker pull
  • docker pulldocker run 都支持使用完整的镜像名称格式 [仓库地址/]<镜像名称>[:标签] 来指定从哪个仓库拉取镜像。
  • ghcr.nju.edu.cn/open-webui/open-webui:main 中的 ghcr.nju.edu.cn 就是指定了仓库地址,所以 docker pull ghcr.nju.edu.cn/open-webui/open-webui:main 这个命令是完全正确的,它会直接从南京大学的镜像站拉取。
  • 你之前关于“不能指定地址”的困惑,是因为你想在 docker pull 命令中指定的是一个镜像加速器来拉取 docker.io 的镜像,而加速器是通过 Daemon 配置而非 pull 命令参数指定的。

你在 Open WebUI 命令中使用的 ghcr.nju.edu.cn 本身就是一个国内的镜像站点,它直接提供了 Open WebUI 的镜像,所以你可以直接指定它来拉取,无需通过 Docker Hub 的加速器设置。

1
docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.nju.edu.cn/open-webui/open-webui:main

Docker加速源及其工作原理

什么是 Docker 镜像加速源?

Docker 镜像加速源(或称为 Registry Mirror)是一个用于存放 Docker 镜像副本的服务器。它通常位于某个特定区域,与该区域的用户网络连接更顺畅、速度更快(例如国内源)。

最常见的镜像加速源是针对 Docker Hub (docker.io) 的加速源,因为 Docker Hub 是官方和社区托管大量公共镜像的主要平台,但在某些地区访问可能会受限或速度很慢。

可以简单理解为:它就像一个“区域分店”或者“缓存服务器”,提供 Docker Hub 里的“商品”(镜像)。

使用加速源主要是为了解决以下问题:

  1. 网络访问限制: 在国内,由于GFW防火墙原因,直接连接 Docker Hub 的官方服务器 (registry-1.docker.io) 可能会连接失败、超时或速度非常慢。
  2. 下载速度慢: 即便没有完全屏蔽,跨国下载镜像的速度通常也远不如从本地或国内服务器下载快。

使用镜像加速源可以有效地绕过这些问题,显著提高拉取 Docker 镜像的下载速度和成功率。

镜像加速源的工作原理

配置了 Docker 镜像加速源后,Docker Daemon (Docker 守护进程) 在拉取镜像时的行为会发生变化:

  1. 用户发起拉取请求: 在命令行执行 docker pull <镜像名称>:<标签>,例如 docker pull ubuntu:latest
  2. Daemon 检查配置: Docker Daemon 接收到这个请求,并检查其配置中是否有针对目标仓库(比如 docker.io)配置了镜像加速源。
  3. 请求重定向: 如果配置了加速源,Daemon 会截获原本要发送给 registry-1.docker.io 的请求,并将其重定向发送给你配置的镜像加速源地址(例如 https://mirror-address)。
  4. 加速源响应请求:
    • 加速源服务器接收到请求后,首先查看本地是否缓存了需要的镜像 (image layers)。
    • 如果已缓存: 加速源直接将本地缓存的镜像层发送给我的请求PC,由于加速源离我的更近,网络通常更好,所以下载速度很快。
    • 如果未缓存: 加速源会作为代理,主动去连接原始仓库 (registry-1.docker.io) 下载该镜像层。加速源服务器通常拥有更好的网络条件,能够更快、更稳定地从原始仓库下载。加速源下载完成后,会先将镜像层缓存到自己本地,然后再发送给我的服务器或PC。
  5. 服务器从加速源下载: 我的 Docker Daemon 从加速源服务器下载镜像。

整个过程对用户是相对透明的: 我仍然使用 docker pull ubuntu 这样的原始命令,但实际的数据传输路径已经从我的服务器直连 docker.io 变成了我的服务器 ---> 加速源---> docker.io(如果加速源没有缓存)。

核心特点:

  • 代理与缓存: 镜像加速源充当代理并具备缓存功能。
  • Daemon 级别: 配置是针对整个 Docker Daemon 生效的。
  • 透明使用: 大多数情况下,拉取 Docker Hub 镜像的命令不需要改变。
  • 提高速度与成功率: 通过国内高速网络和缓存来加速下载。

如何配置docker加速源

配置多个镜像源后,Docker Daemon 会按照列表中配置的顺序,依次尝试连接这些加速器来拉取镜像。

第一步:获取可靠的镜像加速源地址

从国内云服务商(如阿里云、腾讯云等)或公共镜像站获取专属或公共加速源地址。例如:

  • https://阿里云加速器ID.mirror.aliyuncs.com
  • https://mirror.ccs.tencentyun.com
  • https://docker.mirrors.ustc.edu.cn

第二步:创建或编辑 Docker 配置文件 daemon.json

Docker 的主要配置文件是 /etc/docker/daemon.json。如果文件不存在,就创建一个。

使用文本编辑器(如 nanovim)打开或创建文件:

1
sudo vim /etc/docker/daemon.json

第三步:添加或修改 registry-mirrors 配置

在打开的文件中,添加或修改(已有) registry-mirrors 字段。这是一个 JSON 格式的数组(列表),每个元素是一个字符串,代表一个加速源地址。如果要添加多个命令可以从数组中将镜像地址用英文逗号隔开,如一下示例

1
{"registry-mirrors": ["https://docker.xuanyuan.me","https://1ms.run"]}

daemon.json加速源配置

第四步:重新加载 systemd 守护进程配置

通知 systemd Docker 的配置文件已被修改

1
sudo systemctl daemon-reload

第五步:重启 Docker 服务

使 Docker Daemon 读取并应用新的配置文件(可以先关闭docker上正在运行的容器),重启 Docker 服务会停止所有当前正在运行的容器。确保需要的容器配置了自动重启 (--restart always)

1
sudo systemctl restart docker

第六步:验证 Docker 配置是否生效

运行 docker info 命令,检查输出中 Registry Mirrors:是否包含所配置的镜像加速源列表。

1
docker info

服务器docker镜像源配置

单次加速与配置源站加速的对比

方式一:配置 Docker Daemon 的镜像加速器 (/etc/docker/daemon.json)

  • 工作原理: 在 Docker Daemon 层面进行配置。尝试拉取 docker.io (Docker Hub) 的镜像时,Daemon 会自动将请求重定向到你配置的镜像加速器地址。
  • 优点:
    • 透明性高: 对于 Docker Hub 的官方镜像和绝大多数第三方托管在 Docker Hub 上的镜像,仍然可以使用原始的镜像名称(如 docker pull ubuntu)。Docker 会在后台自动通过加速器下载。
    • 一劳永逸: 配置一次后,对所有 Docker Hub 镜像的拉取都有效。
    • 可能提供更完整的镜像: 优秀的镜像源会比较完整地同步 Docker Hub 的内容。
  • 缺点:
    • 需要修改 Daemon 配置: 需要编辑 /etc/docker/daemon.json 文件,并重启 Docker 服务。这需要 root/sudo 权限,且操作相对配置命令复杂一些。
    • 依赖镜像加速器: 依赖于选择的加速器服务的稳定性、速度和镜像完整性。如果加速器本身有问题,所有拉取都会受影响。
    • 主要针对 docker.io 通常只对 Docker Hub 的镜像起作用,对于其他第三方 Registry (如 Quay.io, GCR 等) 的镜像,可能还需要其他加速手段或直接访问。

方式二:直接指定国内的镜像仓库地址

  • 工作原理: 要拉取的镜像名称本身就包含了国内某个仓库的地址,例如 docker pull ghcr.nju.edu.cn/open-webui/open-webui:maindocker pull registry.aliyuncs.com/your-namespace/your-image:tag。Docker 会直接去这个指定的地址拉取镜像。
  • 优点:
    • 无需修改 Daemon 配置: 这是一个 per-command (单次命令) 的行为,不需要修改 /etc/docker/daemon.json 或重启 Docker。
    • 目标明确: 你直接指定了从哪个仓库下载。
    • 绕过 docker.io 访问限制: 只要我的服务器能够访问这个国内仓库地址,就可以下载镜像。
  • 缺点:
    • 依赖镜像可用性: 最大的限制是,需要下载的镜像必须在这个国内仓库中存在。很多国内仓库(特别是云服务商的公共镜像仓库或一些大学的镜像站)可能只包含了 Docker Hub 上最流行的一些镜像,或者他们自己用户上传的镜像,而不会是 Docker Hub 的完整镜像库。
    • 镜像名称不透明: 需要知道镜像在这个国内仓库中的完整名称和路径。同一个镜像在不同的国内仓库中可能命名不同。例如,Docker Hub 上的 ubuntu 镜像在某些国内仓库可能需要写成 registry.aliyuncs.com/google_containers/ubuntu (实际路径各异) 或其他形式。不能直接使用 docker pull ubuntu
    • 不具备通用性: 这种方式只对指定的这个国内仓库有效。如果需要拉取来自其他仓库的镜像,可能需要找它们在其他国内仓库中的对应地址。

如果不方便配置 Docker Daemon 的镜像加速器 (例如没有 root 权限、不想重启 Docker、或者配置总是失败),那么 直接指定国内的镜像仓库地址 ([仓库地址[:端口]/]镜像名称[:标签]) 是一种可行的替代方式 来实现国内下载。

但是,它的前提是:我需要下载的那个具体的镜像,必须在所指定的那个国内仓库中能够找到。

例如,之前能通过 docker pull ghcr.nju.edu.cn/open-webui/open-webui:main 成功拉取 Open WebUI,是因为南京大学的镜像站提供了这个镜像。如果需要拉取 Docker Hub 上的 mysql 镜像,可能需要在阿里云、腾讯云或其他国内云服务商的镜像仓库里查找 mysql 镜像的对应地址(例如 registry.aliyuncs.com/library/mysql:latest 或其他路径),然后使用 docker pull registry.aliyuncs.com/library/mysql:latest 来拉取。

选择哪种方式取决于具体情况:

  • 如果需要频繁拉取各种各样的 Docker Hub 镜像,并且有权限方便地修改 Docker Daemon 配置,那么配置镜像加速器是更省心、更透明的首选方式
  • 如果只需要拉取少数几个已知在国内特定仓库中存在的镜像,或者暂时不想动 Docker Daemon 配置,那么直接指定国内仓库地址的方式可以作为一种临时的或针对特定镜像的解决方案。

无论选择哪种方式,都需要确保服务器能够正常进行 DNS 解析 (能够解析出镜像仓库的域名对应的 IP 地址) 并且服务器到镜像仓库的网络是连通的,这都是下载镜像的基础。

遇到过主要问题

  1. 错误信息:Error response from daemon: Get "https://registry-1.docker.io/v2/": ... Timeout
    • 原因: 即使配置了加速器,Docker Daemon 仍然尝试直接连接 registry-1.docker.io 并超时。这通常意味着配置的加速器没有生效,或者加速器本身不可用导致 Docker 回源。
    • 排查:
      • 再次检查 /etc/docker/daemon.json 文件是否有语法错误。
      • 确认执行了 sudo systemctl daemon-reloadsudo systemctl restart docker
      • 再次用 docker info 确认加速器地址是否正确显示。
      • 测试服务器到加速器地址的网络连通性: 使用 curl -I https://加速器地址 在服务器上测试是否能连接。
  2. 错误信息:curl: (6) Could not resolve host: docker.mirrors.ustc.edu.cn
    • 原因: 这是 DNS 解析失败。服务器无法将域名翻译成 IP 地址。这是比 Docker 配置更基础的网络问题。
    • 排查:
      • 检查服务器的 DNS 配置:查看 /etc/resolv.conf。通常会指向 127.0.0.53 (systemd-resolved) 或其他 DNS 服务器 IP。
      • 检查 systemd-resolved 的状态和上游 DNS 服务器:运行 systemd-resolve --status 查看 DNS Servers 列表。
      • 测试服务器到上游 DNS 服务器的连通性: Ping systemd-resolve --status 中显示的上游 DNS 服务器 IP 地址。
    • 解决: 配置服务器使用可用的国内 DNS 服务器 (如云服务商内网 DNS, 114.114.114.114, 223.5.5.5 等)。修改配置通常通过 Netplan (/etc/netplan/*.yaml) 或 /etc/systemd/resolved.conf,然后应用配置并重启相关服务 (sudo netplan applysudo systemctl restart systemd-resolved)。
    • 验证: DNS 配置修复后,使用 curl -I https://任何国内网站域名 (如 www.baidu.com) 或 curl -I https://你的加速器地址 测试域名解析是否正常。

替代下载方式:直接指定国内镜像仓库地址

如果配置镜像加速器不方便,或者只需要下载特定镜像,可以尝试直接从提供了该镜像的国内仓库拉取:

  • 命令格式: docker pull [国内仓库地址[:端口]/]镜像名称[:标签]
  • 示例: docker pull ghcr.nju.edu.cn/open-webui/open-webui:main (从南京大学镜像站拉取 Open WebUI)
  • 优点: 无需修改 Docker Daemon 配置。
  • 缺点:
    • 你需要知道镜像在这个国内仓库的具体名称和路径。
    • 这个国内仓库必须实际托管了你需要的镜像。

阿里云提供的镜像加速器根本就没用,配置完daemon.json后下载OpenResty(基于 Nginx 的高性能 Web 应用服务器)每次都失败,无论是在1Panel中下载还是直接在服务器中用命令行docker run OpenResty都是失败,一点用都没有,最后还是在CSDN上找到国内仍然可用docker镜像源汇总然后替换掉阿里云提供的镜像加速器才成功下载,网上也有一堆人说这个加速器用不了,即使是阿里云服务器的用户用专属加速链接也拉不下镜像,还得自己去找第三方支持的镜像源站,阿里云真辣鸡。

阿里云提供 docker

相关文章

国内仍然可用docker镜像源汇总,长期维护,定期更新(2025年3月21日)