<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/ DTD/wml_1.1.xml">

<wml>
<head>
<meta http-equiv="cache-control" content="max-age=180,private" />
</head>
<card title="搭建DockerHub代理，Docker设置代理以及加速镜像设置">
<p>
作者:<a href="index.php?action=showuser&amp;userid=1&amp;hash=">admin</a><br />时间:2024-06-11 11:12<br />分类:<a href="index.php?action=list&amp;cid=3&amp;hash=">电脑技术</a><br />内容:
搭建DockerHub代理，Docker设置代理以及加速镜像设置




DockerHub使用CF Workers代码加速


Github：https://github.com/ciiiii/cloudflare-docker-proxy


打开CF Workers创建应用程序，创建项目名docker，使用src/index.js代码


部署好了修改  docker.libcuda.so替换成自己域名


d.iii80.workers.dev 或者在 设置--触发器--自定义域--添加自定义域，也就是自己的域名，例如docker.wan8.eu.org


然后重新部署更新下，搞定，用这两个域名替换代理源。


也可以使用别人搭建的代理或者公共镜像代理，写入到系统配置中。


直接命令写入中国镜像源地址：






XML/HTML代码


    sudo mkdir -p /etc/docker

    sudo tee /etc/docker/daemon.json &lt;&lt;EOF

    {

        &quot;registry-mirrors&quot;: [&quot;https://do.nark.eu.org&quot;]

    }

    EOF

    sudo systemctl daemon-reload

    sudo systemctl restart docker





也可以使用下面命令直接下载：




XML/HTML代码


    原镜像

    docker pull whyour/qinglong:latest

    加速镜像

    docker pull 你的域名/whyour/qinglong:latest





通过http/https代理加速


创建 dockerd 相关的 systemd 目录，这种 .d 目录下的配置将覆盖默认配置


sudo mkdir -p /etc/systemd/system/docker.service.d


新建配置文件 http-proxy.conf


sudo vim /etc/systemd/system/docker.service.d/proxy.conf


添加配置，修改 HTTP 代理的地址








XML/HTML代码


    [Service]

    Environment=&quot;HTTP_PROXY=http://127.0.0.1:10809/&quot;

    Environment=&quot;HTTPS_PROXY=http://127.0.0.1:10809/&quot;

    Environment=&quot;NO_PROXY=127.0.0.1,localhost,192.168.*,*.example.com&quot;





# 如果 `NO_PROXY=*`，那么所有请求都将不通过代理服务器


重新加载配置文件，重启 Dockerd 才能生效


sudo systemctl daemon-reload


sudo systemctl restart docker


检查确认环境变量已经正确配置：


sudo systemctl show --property=Environment docker


可以拉取镜像试试了


以上均以Debian系统测试。




Docker的代理配置




dockerd代理


在执行docker pull时，是由守护进程dockerd来执行。 因此，代理需要配在dockerd的环境中。 而这个环境，则是受systemd所管控，因此实际是systemd的配置。






XML/HTML代码


    sudo mkdir -p /etc/systemd/system/docker.service.d

    sudo touch /etc/systemd/system/docker.service.d/proxy.conf





在这个proxy.conf文件（可以是任意*.conf的形式）中，添加以下内容：






XML/HTML代码


    [Service]

    Environment=&quot;HTTP_PROXY=http://proxy.example.com:8080/&quot;

    Environment=&quot;HTTPS_PROXY=http://proxy.example.com:8080/&quot;

    Environment=&quot;NO_PROXY=localhost,127.0.0.1,.example.com&quot;





其中，proxy.example.com:8080要换成可用的免密代理。 通常使用cntlm在本机自建免密代理，去对接公司的代理。 可参考《Linux下安装配置Cntlm代理》。


Container代理


在容器运行阶段，如果需要代理上网，则需要配置~/.docker/config.json。 以下配置，只在Docker 17.07及以上版本生效。






XML/HTML代码


    {

     &quot;proxies&quot;:

     {

       &quot;default&quot;:

       {

         &quot;httpProxy&quot;: &quot;http://proxy.example.com:8080&quot;,

         &quot;httpsProxy&quot;: &quot;http://proxy.example.com:8080&quot;,

         &quot;noProxy&quot;: &quot;localhost,127.0.0.1,.example.com&quot;

       }

     }

    }




这个是用户级的配置，除了proxies，docker login等相关信息也会在其中。 而且还可以配置信息展示的格式、插件参数等。




此外，容器的网络代理，也可以直接在其运行时通过-e注入http_proxy等环境变量。 这两种方法分别适合不同场景。 config.json非常方便，默认在所有配置修改后启动的容器生效，适合个人开发环境。 在CI/CD的自动构建环境、或者实际上线运行的环境中，这种方法就不太合适，用-e注入这种显式配置会更好，减轻对构建、部署环境的依赖。 当然，在这些环境中，最好用良好的设计避免配置代理上网。


docker build代理


虽然docker build的本质，也是启动一个容器，但是环境会略有不同，用户级配置无效。 在构建时，需要注入http_proxy等参数。






XML/HTML代码


    docker build . \

        --build-arg &quot;HTTP_PROXY=http://proxy.example.com:8080/&quot; \

        --build-arg &quot;HTTPS_PROXY=http://proxy.example.com:8080/&quot; \

        --build-arg &quot;NO_PROXY=localhost,127.0.0.1,.example.com&quot; \

        -t your/image:tag





注意：无论是docker run还是docker build，默认是网络隔绝的。 如果代理使用的是localhost:3128这类，则会无效。 这类仅限本地的代理，必须加上--network host才能正常使用。 而一般则需要配置代理的外部IP，而且代理本身要开启gateway模式。


重启生效


代理配置完成后，reboot重启当然可以生效，但不重启也行。


docker build代理是在执行前设置的，所以修改后，下次执行立即生效。 Container代理的修改也是立即生效的，但是只针对以后启动的Container，对已经启动的Container无效。


dockerd代理的修改比较特殊，它实际上是改systemd的配置，因此需要重载systemd并重启dockerd才能生效。






sudo systemctl daemon-reload


sudo systemctl restart docker


小常识：


Openclash可以直接配置代理


1、系统ip设置成Openclash的IP可以直接旁路由科学


2、打开Openclash的UI管理，设置里面可以直接设置SOCKS5/HTTP(S)代理


默认：HTTP 代理端口 7890    Socks5 代理端口 7891    混合代理端口 7893     允许来自局域网的连接 勾选


3、设置 SOCKS5/HTTP(S) 认证信息（有账号密码认证的代理）




覆写设置--设置 SOCKS5/HTTP(S) 认证信息--添加账号密码




至于Passwwall和ShadowSocksR Plus+也都只默认支持代理转换成SOCKS5代理的。


附改进版 CF Works 代码：




XML/HTML代码


    'use strict'  

      

    const hub_host = 'registry-1.docker.io'  

    const auth_url = 'https://auth.docker.io'  

    const workers_url = 'https://do.nark.eu.org'  

    const workers_host = 'do.nark.eu.org'  

    const home_page_url = 'https://qninq.cn/file/html/dockerproxy.html'  

      

    /** @type {RequestInit} */  

    const PREFLIGHT_INIT = {  

        status: 204,  

        headers: new Headers({  

            'access-control-allow-origin': '*',  

            'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS',  

            'access-control-max-age': '1728000',  

        }),  

    }  

      

    /**  

     * @param {any} body  

     * @param {number} status  

     * @param {Object&lt;string, string&gt;} headers  

     */  

    function makeRes(body, status = 200, headers = {}) {  

        headers['access-control-allow-origin'] = '*'  

        return new Response(body, {status, headers})  

    }  

      

      

    /**  

     * @param {string} urlStr  

     */  

    function newUrl(urlStr) {  

        try {  

            return new URL(urlStr)  

        } catch (err) {  

            return null  

        }  

    }  

      

      

    addEventListener('fetch', e =&gt; {  

        const ret = fetchHandler(e)  

            .catch(err =&gt; makeRes('cfworker error:\n' + err.stack, 502))  

        e.respondWith(ret)  

    })  

      

      

    /**  

     * @param {FetchEvent} e  

     */  

    async function fetchHandler(e) {  

        const getReqHeader = (key) =&gt; e.request.headers.get(key);  

      

        let url = new URL(e.request.url);  

      

        if (url.pathname === '/') {  

            // Fetch and return the home page HTML content with replacement  

            let response = await fetch(home_page_url);  

            let text = await response.text();  

            texttext = text.replace(/{workers_host}/g, workers_host);  

            return new Response(text, {  

                status: response.status,  

                headers: response.headers  

            });  

        }  

      

        if (url.pathname === '/token') {  

            let token_parameter = {  

                headers: {  

                    'Host': 'auth.docker.io',  

                    'User-Agent': getReqHeader(&quot;User-Agent&quot;),  

                    'Accept': getReqHeader(&quot;Accept&quot;),  

                    'Accept-Language': getReqHeader(&quot;Accept-Language&quot;),  

                    'Accept-Encoding': getReqHeader(&quot;Accept-Encoding&quot;),  

                    'Connection': 'keep-alive',  

                    'Cache-Control': 'max-age=0'  

                }  

            };  

            let token_url = auth_url + url.pathname + url.search  

            return fetch(new Request(token_url, e.request), token_parameter)  

        }  

      

        url.hostname = hub_host;  

      

        let parameter = {  

            headers: {  

                'Host': hub_host,  

                'User-Agent': getReqHeader(&quot;User-Agent&quot;),  

                'Accept': getReqHeader(&quot;Accept&quot;),  

                'Accept-Language': getReqHeader(&quot;Accept-Language&quot;),  

                'Accept-Encoding': getReqHeader(&quot;Accept-Encoding&quot;),  

                'Connection': 'keep-alive',  

                'Cache-Control': 'max-age=0'  

            },  

            cacheTtl: 3600  

        };  

      

        if (e.request.headers.has(&quot;Authorization&quot;)) {  

            parameter.headers.Authorization = getReqHeader(&quot;Authorization&quot;);  

        }  

      

        let original_response = await fetch(new Request(url, e.request), parameter)  

        let original_responseoriginal_response_clone = original_response.clone();  

        let original_text = original_response_clone.body;  

        let response_headers = original_response.headers;  

        let newnew_response_headers = new Headers(response_headers);  

        let status = original_response.status;  

      

        if (new_response_headers.get(&quot;Www-Authenticate&quot;)) {  

            let auth = new_response_headers.get(&quot;Www-Authenticate&quot;);  

            let re = new RegExp(auth_url, 'g');  

            new_response_headers.set(&quot;Www-Authenticate&quot;, response_headers.get(&quot;Www-Authenticate&quot;).replace(re, workers_url));  

        }  

      

        if (new_response_headers.get(&quot;Location&quot;)) {  

            return httpHandler(e.request, new_response_headers.get(&quot;Location&quot;))  

        }  

      

        let response = new Response(original_text, {  

            status,  

            headers: new_response_headers  

        })  

        return response;  

      

    }  

      

      

    /**  

     * @param {Request} req  

     * @param {string} pathname  

     */  

    function httpHandler(req, pathname) {  

        const reqreqHdrRaw = req.headers  

      

        // preflight  

        if (req.method === 'OPTIONS' &amp;&amp;  

            reqHdrRaw.has('access-control-request-headers')  

        ) {  

            return new Response(null, PREFLIGHT_INIT)  

        }  

      

        let rawLen = ''  

      

        const reqHdrNew = new Headers(reqHdrRaw)  

      

        const refer = reqHdrNew.get('referer')  

      

        let urlStr = pathname  

      

        const urlObj = newUrl(urlStr)  

      

        /** @type {RequestInit} */  

        const reqInit = {  

            method: req.method,  

            headers: reqHdrNew,  

            redirect: 'follow',  

            body: req.body  

        }  

        return proxy(urlObj, reqInit, rawLen, 0)  

    }  

      

      

    /**  

     *  

     * @param {URL} urlObj  

     * @param {RequestInit} reqInit  

     */  

    async function proxy(urlObj, reqInit, rawLen) {  

        const res = await fetch(urlObj.href, reqInit)  

        const resresHdrOld = res.headers  

        const resHdrNew = new Headers(resHdrOld)  

      

        // verify  

        if (rawLen) {  

            const newLen = resHdrOld.get('content-length') || ''  

            const badLen = (rawLen !== newLen)  

      

            if (badLen) {  

                return makeRes(res.body, 400, {  

                    '--error': `bad len: ${newLen}, except: ${rawLen}`,  

                    'access-control-expose-headers': '--error',  

                })  

            }  

        }  

        const status = res.status  

        resHdrNew.set('access-control-expose-headers', '*')  

        resHdrNew.set('access-control-allow-origin', '*')  

        resHdrNew.set('Cache-Control', 'max-age=1500')  

      

        resHdrNew.delete('content-security-policy')  

        resHdrNew.delete('content-security-policy-report-only')  

        resHdrNew.delete('clear-site-data')  

      

        return new Response(res.body, {  

            status,  

            headers: resHdrNew  

        })  

    }  




只需要修改最上面 do.nark.eu.org 域名为自己绑定的域名或者免费的 workers.dev 域名也可以。


此代码为最简单的 dockerhub 的代理，仅需要新建一个 Workers ，粘贴代码，部署即可，不需要复杂设置。


1Panel代理：https://docker.1panel.live


其他项目：https://github.com/cmliu/CF-Workers-docker.io




国内 Docker 服务状态 &amp; 镜像加速监控：https://status.1panel.top




</p><p>
<a href="index.php?action=login&amp;hash=">立即登陆发表评论</a><br />
</p>
<p><a href="index.php?action=list&amp;hash=">返回日志列表</a><br /><a href="index.php?action=index&amp;hash=">返回主页</a></p>
</card>
</wml>
