关于nginx反代dockerhub的问题

最近想给VPS拉点docker用,发现拉不下来,然后想着自己有个国外VPS,就弄个nginx反代加速一下,然后按照https://github.com/motao123/built-docker 的教程弄好了,但是我尝试拉的时候,出现:
root@lavm-wx45qqhva3:~# docker pull docker.XXXX.com/library/mysql:latest

Error response from daemon: Head “https://docker.XXXX.com/v2/library/mysql/manifests/latest”: G

et "https://auth.docker.io/token?scope=repository%3Alibrary%2Fmysql%3Apull&service=registry.docker.io

": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting he

aders)

root@lavm-wx45qqhva3:~# 不知道是不是我哪里弄错了,我的证书也是申请的Let’s Encrypt 有没有老哥遇到过这样的问题

6 Likes

我觉得有国外 VPS 直接弄个代理它不香吗?通过代理直接访问原地址。

这个国外VPS就是clash节点,只不过我不想在我的VPS上弄clash,我想直接通过nginx反代拉docker,不然我每次买个新VPS,拉docker的时候,都要重新配置clash,老麻烦了,还不如弄个niginx自己用用

反代用caddy
简单很多
你搜下cady反代docker

你用的纯nginx 还是 混合 CF worker 的。

纯nginx,从apt 拉下来的

:joy:那还得重新装环境,还得把nginx卸载,删配置文件啥的,更麻烦了,等等看有没有佬能解决这个问题,不行的话,我再换吧

你配置 nginx 后重新加载过吗?看配置原仓库的配置没问题。还有你确保 VPS 可以直接访问?

重启过nginx服务,我的VPS访问国外VPS是没问题的,

我的国外VPS到dockerhub也是没问题的

:sob:有没有佬遇到过这样的问题,怎么解决啊

auth.docker.io这个docker验证网址国内也墙了,看反代配置并没有把这个流量反代,用AI写一个试试,应该不是多难的事。

1 Like

我看文档后面中有说明遇到这种情况的解决方法,有试过吗

1 Like

:joy:坏了我是瞎子,我试试看 试过了,现在变成认证失败了,我记得拉公共镜像不需要认证啊 :sob:

:cold_sweat: 公共镜像好像是拉取的时候,要去auth拉一个token过来,我在最新的nginx上加了这个,并且我测试的时候能正常拿到token,但是我去拉的时候却拉不下来,显示未认证


image

:sob: 怎么这么难搞啊,有没有佬遇到过这样的问题,怎么解决啊

你把反代的配置文件放上来,敏感的X号代替就行了,不然别人怎么知道是哪里错了呀

这个是反代配置内容:
server {
listen 443 ssl;
server_name docker.XXXX.com;

# SSL 证书路径
ssl_certificate /etc/letsencrypt/live/docker.XXXX.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/docker.XXXX.com/privkey.pem;

# 强制指定 DNS 解析器(必须的)
resolver 1.1.1.1 8.8.8.8 valid=10s;
resolver_timeout 10s;

# 增强 SSL 反向代理兼容性
proxy_ssl_server_name on;
proxy_ssl_protocols TLSv1.2 TLSv1.3;

# 核心配置 - 镜像数据请求
location /v2/ {
    # 关键修复:确保路径精确匹配上游服务器结构,结尾必须带斜杠 "/"
    proxy_pass https://registry-1.docker.io/v2/;  # 修复点:添加 /v2/ 并保留斜杠

    # 强制传递原始域名头
    proxy_set_header Host registry-1.docker.io;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # 严格转发认证头(确保 Token 被正确传递)
    proxy_set_header Authorization $http_authorization;
    proxy_pass_header Authorization;

    # 改写认证服务地址为反代 URL
    proxy_hide_header WWW-Authenticate;
    add_header WWW-Authenticate 'Bearer realm="https://docker.XXXX.com/token",service="registry.docker.io"' always;

    # 关闭缓存,防止数据错乱
    proxy_buffering off;

    # 处理重定向
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 301 302 307 = @handle_redirect;
}

# 核心配置 - Token 认证服务反代
location /token {
    # 修复点:传递原始请求路径参数(如 scope=repository:library/mysql:pull)
    proxy_pass https://auth.docker.io/token$request_uri;
    proxy_set_header Host auth.docker.io;
    proxy_set_header X-Forwarded-Proto $scheme;
}

# 处理重定向逻辑(原内容保留)
location @handle_redirect {
    resolver 1.1.1.1 valid=10s;
    set $saved_redirect_location $upstream_http_location;
    proxy_pass $saved_redirect_location;
    proxy_set_header Host $proxy_host;  # 确保重定向后的 Host 头正确
    proxy_ssl_server_name on;
}

# 日志配置(可选)
access_log /var/log/nginx/docker-registry-access.log;
error_log /var/log/nginx/docker-registry-error.log warn;

}

:joy: 我解决了!

    server {
        listen 443 ssl;
        server_name docker.XXXX.com;

        ssl_certificate 证书地址;
        ssl_certificate_key 密钥地址;

        ssl_session_timeout 24h;
        ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

        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://docker.XXXX.com/token",service="registry.docker.io"' always;

            # 对 upstream 状态码检查,实现 error_page 错误重定向
            proxy_intercept_errors on;
            recursive_error_pages on;
            error_page 301 302 307 = @handle_redirect;
        }

        # 处理 Docker OAuth2 Token 认证请求
        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;

            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;
        }
    }
1 Like
server {
    listen 443 ssl;
    server_name docker.XXXX.com;

    # SSL 证书路径
    ssl_certificate /etc/letsencrypt/live/docker.XXXX.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/docker.XXXX.com/privkey.pem;

    # 强制指定 DNS 解析器
    resolver 1.1.1.1 8.8.8.8 valid=10s;
    resolver_timeout 10s;

    # 增强 SSL 反向代理兼容性
    proxy_ssl_server_name on;
    proxy_ssl_protocols TLSv1.2 TLSv1.3;

    # 核心配置 - 镜像数据请求
    location /v2/ {
        proxy_pass https://registry-1.docker.io/v2/;
        proxy_set_header Host registry-1.docker.io;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Authorization $http_authorization;
        proxy_pass_header Authorization;

        proxy_hide_header WWW-Authenticate;
        add_header WWW-Authenticate 'Bearer realm="https://docker.XXXX.com/token",service="registry.docker.io"' always;

        proxy_buffering off;
        proxy_intercept_errors on;
        recursive_error_pages on;
        error_page 301 302 307 = @handle_redirect;

        access_log /var/log/nginx/v2-access.log;
        error_log /var/log/nginx/v2-error.log debug;
    }

    # 核心配置 - Token 认证服务反代
    location /token {
        proxy_pass https://auth.docker.io/token$is_args$args;
        proxy_set_header Host auth.docker.io;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Authorization $http_authorization;
        proxy_pass_header Authorization;

        access_log /var/log/nginx/token-access.log;
        error_log /var/log/nginx/token-error.log debug;
    }

    # 处理重定向逻辑
    location @handle_redirect {
        resolver 1.1.1.1 valid=10s;
        set $saved_redirect_location $upstream_http_location;
        proxy_pass $saved_redirect_location;
        proxy_set_header Host $proxy_host;
        proxy_set_header Authorization $http_authorization;
        proxy_ssl_server_name on;
    }

    # 日志配置
    access_log /var/log/nginx/docker-registry-access.log;
    error_log /var/log/nginx/docker-registry-error.log warn;
}

试试这个。

感觉用cf的更加方便