前言

随着 Docker Hub 官方源被封锁,国内的镜像源也纷纷下架,现在国内企业和个人服务拉取镜像越来越困难。阿里云、腾讯云等镜像源已经只允许自家服务器使用,其他第三方源也存在稳定性和安全性问题。

所以,自建 Docker Hub 加速镜像就显得很有必要。最常见的做法是:用 Nginx 反向代理 Docker Hub 官方仓库,搭一个属于你自己的"加速入口"。

准备环境

以下是我的环境配置,主打便宜好用,可根据自身情况调整。

  • 系统:Debian / Ubuntu
  • 域名(可选):NameSilo 免备案、价格便宜(.xyz等冷门域名)。没有域名也可以使用自签证书启用 HTTPS

安装 Nginx

sudo apt update
sudo apt install nginx

开放端口

放行 HTTPS 端口(根据自己服务器情况开放端口,以 ufw 为例):

sudo ufw allow 443

配置 Nginx 反代 Docker Hub

创建新配置文件:

touch /etc/nginx/conf.d/dockerhub.conf

编辑配置文件:

nano /etc/nginx/conf.d/dockerhub.conf

将以下内容粘贴进去,把域名和证书路径改为你自己的,本文示例域名your.domain.com。如果还没证书,可以先用 acme.sh 申请自动证书。

如果用的 NameSilo 的域名,可以参考 acme.sh 的 DNS API 自动申请SSL证书:https://github.com/acmesh-official/acme.sh/wiki/dnsapi#35-use-namesilocom-api

#反代docker hub镜像源
server {
    listen 443 ssl;
    server_name your.domain.com;

    ssl_certificate /etc/nginx/ssl/your.domain.com.crt;
    ssl_certificate_key /etc/nginx/ssl/your.domain.com.key;

    ssl_session_timeout 24h;
    ssl_protocols TLSv1.2 TLSv1.3;

    # /v2/ → https://registry-1.docker.io
    location /v2/ {
        proxy_pass https://registry-1.docker.io;  # Docker Hub 的官方镜像仓库
        proxy_set_header Host registry-1.docker.io;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 关闭缓存
        proxy_buffering off;

        # 转发认证相关的头部
        proxy_set_header Authorization $http_authorization;
        proxy_pass_header  Authorization;

        # 重写 www-authenticate 头为你的反代地址
        proxy_hide_header www-authenticate;
        add_header www-authenticate 'Bearer realm="https://your.domain.com/token",service="registry.docker.io"' always;
        # always 参数确保该头部在返回 401 错误时无论什么情况下都会被添加。

        # 对 upstream 状态码检查,实现 error_page 错误重定向
        proxy_intercept_errors on;
        # error_page 指令默认只检查了第一次后端返回的状态码,开启后可以跟随多次重定向。
        recursive_error_pages on;
        # 根据状态码执行对应操作,以下为301、302、307状态码都会触发
        error_page 301 302 307 = @handle_redirect;

    }

    # 处理 Docker OAuth2 Token 认证请求
    # 把返回的 `WWW-Authenticate` 头改写为你的入口地址,保证客户端能在你这儿拿到 token。
    # /token → https://auth.docker.io
    location /token {
        resolver 1.1.1.1 valid=600s;
        proxy_pass https://auth.docker.io;  # Docker 认证服务器

        # 设置请求头,确保转发正确
        proxy_set_header Host auth.docker.io;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 传递 Authorization 头信息,获取 Token
        proxy_set_header Authorization $http_authorization;
        proxy_pass_header Authorization;

        # 禁用缓存
        proxy_buffering off;
    }
    location @handle_redirect {
        resolver 1.1.1.1;
        set $saved_redirect_location '$upstream_http_location';
        proxy_pass $saved_redirect_location;
    }
}

保存退出(Ctrl+O → 回车 → Ctrl+X)。

重载加载 Nginx 配置

sudo nginx -s reload

如果没有报错说明配置生效。

配置 Docker 镜像源

你现在有一个新的私有镜像仓库:https://your.domain.com

接下来让 Docker 走这个仓库,而不是默认的 https://registry-1.docker.io。下面我分几种常见情况讲清楚该怎么做👇

一、临时使用(单次命令)

如果只是想临时从该仓库拉取镜像,例如:

docker pull your.domain.com/ubuntu:latest

或者运行:

docker run -it your.domain.com/ubuntu bash

这种方式不需要修改配置文件。但要注意:

  • 镜像名前必须加上完整域名(域名)
  • 若仓库未使用有效证书(自签名或内部 CA),还需要配置 Docker 信任

二、长期替换默认仓库(推荐)

如果你想让 Docker 默认就从新的仓库拉取镜像,可以通过以下两种方式配置:

方式 1️⃣:修改 /etc/docker/daemon.json

编辑(或新建)文件:

sudo nano /etc/docker/daemon.json

加入以下内容(若已有其他字段请合并):

{
  "registry-mirrors": ["https://your.domain.com"]
}

然后执行:

sudo systemctl daemon-reload
sudo systemctl restart docker

验证:

docker info | grep -A1 "Registry Mirrors"

输出中应出现:

Registry Mirrors:
 https://your.domain.com/

✅ 说明生效。

方式 2️⃣:使用自定义私有仓库(带认证)

如果你的仓库需要登录(例如 Harbor、Nexus 等),可登录:

docker login your.domain.com

然后输入用户名密码。成功后会在 ~/.docker/config.json 中保存凭据。

注意!如果利用反代服务器登录 docker hub 仓库,反代服务器是可以获取到你的账号密码的,所以请谨慎使用他人搭建的服务登录!如果没有拉取自己的私有仓库的镜像的需求,保持匿名拉取相对会安全一些。

三、如果是自签名证书(HTTPS)

若你的 https://your.domain.com 使用自签名证书(非 Let’s Encrypt 等正规证书),Docker 会拒绝连接。

解决方法:

  1. 创建目录:

    sudo mkdir -p /etc/docker/certs.d/your.domain.com
    
  2. 将证书(例如 ca.crt)复制进去:

    sudo cp ca.crt /etc/docker/certs.d/your.domain.com/
    
  3. 重启 Docker:

    sudo systemctl restart docker
    

如果你没有证书,可以临时在 daemon.json 加上:

{"insecure-registries": ["your.domain.com"]}

但⚠️这只适合内网或测试环境,生产环境请务必使用 HTTPS 证书。

四、验证是否成功

用的临时方案则执行:

docker pull your.domain.com/library/hello-world

用的替换默认仓库方案则执行:

docker pull hello-world

拉取成功,你的加速镜像已经生效!

五、安全配置

目前你的 Nginx Docker Hub 镜像是搭建成功了,但默认是公开可访问的,任何人只要知道你的域名,都能用你的服务器中转 Docker Hub。如果被人滥用,会导致:

  • 你的服务器带宽被占满
  • Docker Hub 对你服务器的出口 IP 限速
  • 甚至触发风控或账单暴涨

所以确实需要加一层访问控制,让只有你(或你的机器)能用。很多教程都忽略了这一点。

IP 白名单限制(推荐小团队/个人)

最简单的办法就是IP 白名单限制, 在你的反代配置/etc/nginx/conf.d/dockerhub.conf里,只允许特定 IP 访问 /v2/ 和 /token。

示例:

location /v2/ {
    allow 你的本地公网IP;      # 比如 allow 123.45.67.89;
    allow 你的公司出口IP;      # 可写多个 allow
    deny all;                # 其他一律拒绝
    ...
}
location /token {
    allow 你的本地公网IP;
    allow 你的公司出口IP;
    deny all;
    ...
}

✅ 优点:简单高效,无需额外配置
⚠️ 缺点:如果你经常换网络(如笔电或多地服务器),需要手动更新 IP

修改后重新加载 nginx 配置

nginx -s reload

好了,完事。


总结

通过本文的详细步骤,您可以成功搭建一个属于自己的 Docker Hub 加速镜像服务。这种方案相比使用公共镜像源有以下优势:

  1. 稳定性:不受公共镜像源服务质量影响
  2. 安全性:可以配置 IP 白名单,限制访问范围
  3. 可控性:完全掌控服务状态和配置
  4. 性能优化:选择距离用户更近的服务器节点

虽然搭建过程相对复杂,但一旦配置完成,就能为您的 Docker 镜像拉取提供稳定可靠的服务保障。


本文转载自技术好学屋,原文地址:自建 Docker Hub 加速镜像(Nginx 反向代理方案)