利用GitHub配置镜像加速,解决 Docker镜像拉取问题

docker pull nginx 卡了两分钟,结果甩给我一句 <font style="color:#c00;">TLS handshake timeout</font>,连换三四个国内加速器,不是 404 就是 unauthorized。

不用买代理、不用租境外服务器,一个 GitHub 仓库加一段 Actions,让海外机器帮你拉好、打包,下载回本地 docker load 直接用。

最终成品就是这个公开仓库,README 写明它是"Docker 镜像同步中转站"

一、场景:现在拉镜像到底卡在哪

国内直连 Docker Hub(Docker 官方镜像仓库)的链路本身不稳定,过去大家习惯在 /etc/docker/daemon.json 里配 registry-mirrors 走加速器,而近一两年大批公开加速器陆续关停。

我这边反复出现的报错可以归成四类:

现象 / 报错 直接原因
TLS handshake timeout、i/o timeout 直连 Docker Hub 握手超时
加速器返回 404 Not Found 镜像站域名已关停或停止代理
toomanyrequests: too many requests 匿名拉取触发 Docker Hub 限速
拉到一半断在 Pulling fs layer 长连接被中断,链路不稳

加速器地址今天能用、明天挂,每失效一次就得改配置、重启 docker。那有没有一台"身在海外、能连 Docker Hub、还免费"的机器,能替我把镜像拉下来?

二、原理:GitHub Actions 凭什么能当中转站

GitHub Actions(GitHub 内置的持续集成服务)的运行器(runner)部署在海外机房,默认就能正常访问 Docker Hub。工作流里的 docker pull 走的是 GitHub 机房到 Docker Hub 的网络,和你本机的网络环境无关。

整条链路的数据流向是这样的:

latex 复制代码
你的本机(国内)          GitHub 运行器(海外)          Docker Hub
     |                         |                         |
     | ① 触发工作流             |                         |
     | ----------------------> |                         |
     |                         | ② docker pull           |
     |                         | ----------------------> |
     |                         | <====== 镜像层 ======== |
     |                         |                         |
     |                         | ③ save | gzip 打包       |
     | ④ 下载产物(zip)          |                         |
     | <---------------------- |                         |
     |                         |                         |
     | ⑤ unzip + docker load   |

三、一个 workflow 文件搞定

你可以直接用我建好的仓库:https://github.com/ruigeda/Dockerbuild ;也可以在自己的公开仓库里新建文件 .github/workflows/save-image.yml,内容如下:

yaml 复制代码
name: image_name
on:
  workflow_dispatch:
    inputs:
      image_name:
        description: '镜像全名,例如 postgres:16 或 redis:7-alpine'
        required: true
      platform:
        description: '目标架构'
        default: 'linux/amd64'

jobs:
  pull_and_save:
    runs-on: ubuntu-latest
    steps:
      - name: Login to Docker Hub (突破匿名限速)
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
        continue-on-error: true   # 如果没配密钥也不中断

      - name: Pull & Save & Compress
        run: |
          docker pull --platform ${{ github.event.inputs.platform }} ${{ github.event.inputs.image_name }}
          
          # 用镜像名中的 tag 作为文件名,避免特殊字符
          SAFE_NAME=$(echo "${{ github.event.inputs.image_name }}" | tr '/:' '_')
          
          # docker save 后立刻 gzip,体积通常能压到 30%~50%
          docker save ${{ github.event.inputs.image_name }} | gzip > ${SAFE_NAME}.tar.gz
          
          ls -lh ${SAFE_NAME}.tar.gz

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: docker-image
          path: "*.tar.gz"
          retention-days: 5   # 只保留5天,省空间

工作流在网页上默认显示的名字,就是文件第一行 name 后面的值。你可以把 image_name 改成自己好认的名字,比如 镜像中转:

name 字段同时决定左侧工作流列表里显示的名称

注意:这一步只改显示名,真正决定拉哪个镜像的是运行时填写的参数,别把两者搞混。

四、实操验证:从触发到本地跑通

步骤 1:进入 Actions 页面

打开仓库顶部的 Actions 标签,左侧选中你的工作流,右侧能看到绿色的 Run workflow 按钮。

步骤 2:填写镜像全名

点 Run workflow,在弹窗里输入要拉的镜像,这里以 nginx 为例;目标架构保持默认 linux/amd64,再点一次绿色 Run workflow 提交。

镜像名要写完整,带 tag 的写法如 postgres:16、redis:7-alpine;**只写 nginx 等价于 **nginx:latest。

步骤 3:等待运行完成

几十秒后,列表里出现一条绿色对勾的运行记录,我这次只用了 26 秒。

没配密钥时,Annotations 里可能出现一条红色 Username and password required,属于登录步骤的提示,因设置了容错不影响结果

步骤 4:下载产物

点进这条记录,拉到页面最底部 Artifacts 区域,能看到名为 docker-image 的压缩包,点击下载。

步骤 5:拿到 zip 包

浏览器下载下来的是 docker-image.zip,我这个包约 60 MB,是 nginx 压缩后的体积。

步骤 6:传到 Linux 并加载

把 zip 传到你的 Linux 机器(或 WSL),解压、加载、确认:

bash 复制代码
unzip docker-image.zip
docker load -i *.tar.gz
docker images

终端返回如下结果,说明镜像已经原样进了本地镜像库:

latex 复制代码
Archive:  docker-image.zip
  inflating: nginx.tar.gz
Loaded image: nginx:latest

docker images 能看到 nginx:latest,镜像 100% 可用,全程没碰本机的 Docker Hub 连接

镜像加载回来,再顺手起个容器确认能跑:

bash 复制代码
docker run -d --name web -p 8080:80 nginx

浏览器访问 http://本机IP:8080 看到 nginx 欢迎页,整条链路才算彻底闭环。

五、总结延伸

这套方案的本质,是把"拉镜像"这件网络受困的事,外包给海外的 GitHub 运行器,再用产物(artifact)把结果运回本地:

  • 拉取环境:海外运行器直连 Docker Hub,无需代理
  • 分发形式:docker save + gzip 压缩,产物以 artifact 下载
  • 复用方式:手动触发 + 参数化,换镜像只改一个输入框

几百 MB 的常规镜像走这条路又快又稳;多 GB 的超大镜像受上传下载耗时影响,建议优先考虑专用镜像仓库。

术语速查表

术语 含义
Docker Hub Docker 官方公共镜像仓库
Registry(镜像仓库) 存储和分发容器镜像的服务
GitHub Actions GitHub 提供的持续集成 / 自动化服务
workflow(工作流) 定义自动化任务的 YAML 文件
runner(运行器) 实际执行工作流的机器
artifact(产物) 工作流运行后上传、可供下载的文件
platform(架构) 镜像运行的目标平台,如 linux/amd64

参考链接

相关推荐
Huangjin007_1 小时前
【Linux 系统篇(二十八)】文件(五):Ext 系列文件系统(下):Ext2块组结构,inode与文件寻址原理
linux·运维·服务器
小陈运维1 小时前
使用kubeadm初始化IPV4/IPV6集群
linux·docker·云原生·容器·kubernetes
Wang's Blog2 小时前
Java 项目部署之 Docker工具快速入门: 容器命令练习:创建、改文件、重启到删除的完整闭环
java·开发语言·docker
怕浪猫2 小时前
AI Agent 的安全怎么保障?面试最后一关的终极问题
算法·面试·github
笑洋仟2 小时前
k8s的Ingress配置问题
云原生·容器·kubernetes
m4Rk_2 小时前
【论文阅读】Agent 记忆机制(97):MCMA——让 Agent 学会如何抽象记忆,实现跨任务经验迁移
论文阅读·人工智能·学习·开源·github
垚垚学技术_聚焦云原生2 小时前
K8s OpenEBS LVM 动态存储 PVC Pending 排查记
云原生·容器·kubernetes
小锋学长生活大爆炸2 小时前
【工具】在 Android 手机上运行 Docker
android·docker·智能手机
miofly2 小时前
GitHub 日榜趋势速报 | 2026-10-12
开源·github