记录我的一些生活写照、无聊的牢骚、内心世界的活动 注册 | 登陆

搭建DockerHub代理,Docker设置代理以及加速镜像设置

搭建DockerHub代理,Docker设置代理以及加速镜像设置
DockerHub使用CF Workers代码加速
打开CF Workers创建应用程序,创建项目名docker,使用src/index.js代码
部署好了修改  docker.libcuda.so替换成自己域名
d.iii80.workers.dev 或者在 设置--触发器--自定义域--添加自定义域,也就是自己的域名,例如docker.wan8.eu.org
然后重新部署更新下,搞定,用这两个域名替换代理源。
也可以使用别人搭建的代理或者公共镜像代理,写入到系统配置中。
直接命令写入中国镜像源地址:
XML/HTML代码
  1. sudo mkdir -p /etc/docker
  2. sudo tee /etc/docker/daemon.json <<EOF
  3. {
  4.     "registry-mirrors": ["https://do.nark.eu.org"]
  5. }
  6. EOF
  7. sudo systemctl daemon-reload
  8. sudo systemctl restart docker
也可以使用下面命令直接下载:
XML/HTML代码
  1. 原镜像
  2. docker pull whyour/qinglong:latest
  3. 加速镜像
  4. 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代码
  1. [Service]
  2. Environment="HTTP_PROXY=http://127.0.0.1:10809/"
  3. Environment="HTTPS_PROXY=http://127.0.0.1:10809/"
  4. Environment="NO_PROXY=127.0.0.1,localhost,192.168.*,*.example.com"
# 如果 `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代码
  1. sudo mkdir -p /etc/systemd/system/docker.service.d
  2. sudo touch /etc/systemd/system/docker.service.d/proxy.conf
在这个proxy.conf文件(可以是任意*.conf的形式)中,添加以下内容:
XML/HTML代码
  1. [Service]
  2. Environment="HTTP_PROXY=http://proxy.example.com:8080/"
  3. Environment="HTTPS_PROXY=http://proxy.example.com:8080/"
  4. Environment="NO_PROXY=localhost,127.0.0.1,.example.com"
其中,proxy.example.com:8080要换成可用的免密代理。 通常使用cntlm在本机自建免密代理,去对接公司的代理。 可参考《Linux下安装配置Cntlm代理》。
Container代理
在容器运行阶段,如果需要代理上网,则需要配置~/.docker/config.json。 以下配置,只在Docker 17.07及以上版本生效。
XML/HTML代码
  1. {
  2.  "proxies":
  3.  {
  4.    "default":
  5.    {
  6.      "httpProxy": "http://proxy.example.com:8080",
  7.      "httpsProxy": "http://proxy.example.com:8080",
  8.      "noProxy": "localhost,127.0.0.1,.example.com"
  9.    }
  10.  }
  11. }
这个是用户级的配置,除了proxies,docker login等相关信息也会在其中。 而且还可以配置信息展示的格式、插件参数等。
此外,容器的网络代理,也可以直接在其运行时通过-e注入http_proxy等环境变量。 这两种方法分别适合不同场景。 config.json非常方便,默认在所有配置修改后启动的容器生效,适合个人开发环境。 在CI/CD的自动构建环境、或者实际上线运行的环境中,这种方法就不太合适,用-e注入这种显式配置会更好,减轻对构建、部署环境的依赖。 当然,在这些环境中,最好用良好的设计避免配置代理上网。
docker build代理
虽然docker build的本质,也是启动一个容器,但是环境会略有不同,用户级配置无效。 在构建时,需要注入http_proxy等参数。
XML/HTML代码
  1. docker build . \
  2.     --build-arg "HTTP_PROXY=http://proxy.example.com:8080/" \
  3.     --build-arg "HTTPS_PROXY=http://proxy.example.com:8080/" \
  4.     --build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" \
  5.     -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代码
  1. 'use strict'  
  2.   
  3. const hub_host = 'registry-1.docker.io'  
  4. const auth_url = 'https://auth.docker.io'  
  5. const workers_url = 'https://do.nark.eu.org'  
  6. const workers_host = 'do.nark.eu.org'  
  7. const home_page_url = 'https://qninq.cn/file/html/dockerproxy.html'  
  8.   
  9. /** @type {RequestInit} */  
  10. const PREFLIGHT_INIT = {  
  11.     status: 204,  
  12.     headers: new Headers({  
  13.         'access-control-allow-origin': '*',  
  14.         'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS',  
  15.         'access-control-max-age': '1728000',  
  16.     }),  
  17. }  
  18.   
  19. /**  
  20.  * @param {any} body  
  21.  * @param {number} status  
  22.  * @param {Object<string, string>} headers  
  23.  */  
  24. function makeRes(body, status = 200headers = {}) {  
  25.     headers['access-control-allow-origin'] = '*'  
  26.     return new Response(body, {status, headers})  
  27. }  
  28.   
  29.   
  30. /**  
  31.  * @param {string} urlStr  
  32.  */  
  33. function newUrl(urlStr) {  
  34.     try {  
  35.         return new URL(urlStr)  
  36.     } catch (err) {  
  37.         return null  
  38.     }  
  39. }  
  40.   
  41.   
  42. addEventListener('fetch', e => {  
  43.     const ret = fetchHandler(e)  
  44.         .catch(err => makeRes('cfworker error:\n' + err.stack, 502))  
  45.     e.respondWith(ret)  
  46. })  
  47.   
  48.   
  49. /**  
  50.  * @param {FetchEvent} e  
  51.  */  
  52. async function fetchHandler(e) {  
  53.     const getReqHeader = (key) => e.request.headers.get(key);  
  54.   
  55.     let url = new URL(e.request.url);  
  56.   
  57.     if (url.pathname === '/') {  
  58.         // Fetch and return the home page HTML content with replacement  
  59.         let response = await fetch(home_page_url);  
  60.         let text = await response.text();  
  61.         texttext = text.replace(/{workers_host}/g, workers_host);  
  62.         return new Response(text, {  
  63.             status: response.status,  
  64.             headers: response.headers  
  65.         });  
  66.     }  
  67.   
  68.     if (url.pathname === '/token') {  
  69.         let token_parameter = {  
  70.             headers: {  
  71.                 'Host': 'auth.docker.io',  
  72.                 'User-Agent': getReqHeader("User-Agent"),  
  73.                 'Accept': getReqHeader("Accept"),  
  74.                 'Accept-Language': getReqHeader("Accept-Language"),  
  75.                 'Accept-Encoding': getReqHeader("Accept-Encoding"),  
  76.                 'Connection': 'keep-alive',  
  77.                 'Cache-Control': 'max-age=0'  
  78.             }  
  79.         };  
  80.         let token_url = auth_url + url.pathname + url.search  
  81.         return fetch(new Request(token_url, e.request), token_parameter)  
  82.     }  
  83.   
  84.     url.hostname = hub_host;  
  85.   
  86.     let parameter = {  
  87.         headers: {  
  88.             'Host': hub_host,  
  89.             'User-Agent': getReqHeader("User-Agent"),  
  90.             'Accept': getReqHeader("Accept"),  
  91.             'Accept-Language': getReqHeader("Accept-Language"),  
  92.             'Accept-Encoding': getReqHeader("Accept-Encoding"),  
  93.             'Connection': 'keep-alive',  
  94.             'Cache-Control': 'max-age=0'  
  95.         },  
  96.         cacheTtl: 3600  
  97.     };  
  98.   
  99.     if (e.request.headers.has("Authorization")) {  
  100.         parameter.headers.Authorization = getReqHeader("Authorization");  
  101.     }  
  102.   
  103.     let original_response = await fetch(new Request(url, e.request), parameter)  
  104.     let original_responseoriginal_response_clone = original_response.clone();  
  105.     let original_text = original_response_clone.body;  
  106.     let response_headers = original_response.headers;  
  107.     let newnew_response_headers = new Headers(response_headers);  
  108.     let status = original_response.status;  
  109.   
  110.     if (new_response_headers.get("Www-Authenticate")) {  
  111.         let auth = new_response_headers.get("Www-Authenticate");  
  112.         let re = new RegExp(auth_url, 'g');  
  113.         new_response_headers.set("Www-Authenticate", response_headers.get("Www-Authenticate").replace(re, workers_url));  
  114.     }  
  115.   
  116.     if (new_response_headers.get("Location")) {  
  117.         return httpHandler(e.request, new_response_headers.get("Location"))  
  118.     }  
  119.   
  120.     let response = new Response(original_text, {  
  121.         status,  
  122.         headers: new_response_headers  
  123.     })  
  124.     return response;  
  125.   
  126. }  
  127.   
  128.   
  129. /**  
  130.  * @param {Request} req  
  131.  * @param {string} pathname  
  132.  */  
  133. function httpHandler(req, pathname) {  
  134.     const reqreqHdrRaw = req.headers  
  135.   
  136.     // preflight  
  137.     if (req.method === 'OPTIONS' &&  
  138.         reqHdrRaw.has('access-control-request-headers')  
  139.     ) {  
  140.         return new Response(null, PREFLIGHT_INIT)  
  141.     }  
  142.   
  143.     let rawLen = ''  
  144.   
  145.     const reqHdrNew = new Headers(reqHdrRaw)  
  146.   
  147.     const refer = reqHdrNew.get('referer')  
  148.   
  149.     let urlStr = pathname  
  150.   
  151.     const urlObj = newUrl(urlStr)  
  152.   
  153.     /** @type {RequestInit} */  
  154.     const reqInit = {  
  155.         method: req.method,  
  156.         headers: reqHdrNew,  
  157.         redirect: 'follow',  
  158.         body: req.body  
  159.     }  
  160.     return proxy(urlObj, reqInit, rawLen, 0)  
  161. }  
  162.   
  163.   
  164. /**  
  165.  *  
  166.  * @param {URL} urlObj  
  167.  * @param {RequestInit} reqInit  
  168.  */  
  169. async function proxy(urlObj, reqInit, rawLen) {  
  170.     const res = await fetch(urlObj.href, reqInit)  
  171.     const resresHdrOld = res.headers  
  172.     const resHdrNew = new Headers(resHdrOld)  
  173.   
  174.     // verify  
  175.     if (rawLen) {  
  176.         const newLen = resHdrOld.get('content-length') || ''  
  177.         const badLen = (rawLen !== newLen)  
  178.   
  179.         if (badLen) {  
  180.             return makeRes(res.body, 400, {  
  181.                 '--error': `bad len: ${newLen}, except: ${rawLen}`,  
  182.                 'access-control-expose-headers': '--error',  
  183.             })  
  184.         }  
  185.     }  
  186.     const status = res.status  
  187.     resHdrNew.set('access-control-expose-headers', '*')  
  188.     resHdrNew.set('access-control-allow-origin', '*')  
  189.     resHdrNew.set('Cache-Control', 'max-age=1500')  
  190.   
  191.     resHdrNew.delete('content-security-policy')  
  192.     resHdrNew.delete('content-security-policy-report-only')  
  193.     resHdrNew.delete('clear-site-data')  
  194.   
  195.     return new Response(res.body, {  
  196.         status,  
  197.         headers: resHdrNew  
  198.     })  
  199. }  
只需要修改最上面 do.nark.eu.org 域名为自己绑定的域名或者免费的 workers.dev 域名也可以。
此代码为最简单的 dockerhub 的代理,仅需要新建一个 Workers ,粘贴代码,部署即可,不需要复杂设置。
国内 Docker 服务状态 & 镜像加速监控:https://status.1panel.top

« 上一篇 | 下一篇 »

发表评论

评论内容 (必填):