{"id":528,"date":"2024-06-11T23:01:57","date_gmt":"2024-06-11T15:01:57","guid":{"rendered":"https:\/\/sharebits.link\/?p=528"},"modified":"2024-06-11T23:07:07","modified_gmt":"2024-06-11T15:07:07","slug":"%e8%87%aa%e5%bb%badocker%e7%bc%93%e5%ad%98%e5%8a%a0%e9%80%9f%e5%99%a8","status":"publish","type":"post","link":"https:\/\/sharebits.link\/?p=528","title":{"rendered":"\u81ea\u5efaDocker\u7f13\u5b58\u52a0\u901f\u5668"},"content":{"rendered":"<h3 id=\"\u65b9\u6cd51-\u955c\u50cf\u8f6c\u5b58\">\u65b9\u6cd51\uff1a\u955c\u50cf\u8f6c\u5b58<\/h3>\n<p>\u501f\u52a9Github\u548c\u963f\u91cc\u4e91\u955c\u50cf\u4ed3\u5e93\uff0c\u8f6c\u5b58\u955c\u50cf\u3002<\/p>\n<p>\u5177\u4f53\u65b9\u6cd5\u53c2\u8003\uff1a<a href=\"https:\/\/www.bilibili.com\/read\/cv35249690\/\">https:\/\/www.bilibili.com\/read\/cv35249690\/<\/a><\/p>\n<p>\ud83d\udc4d \u4f18\u70b9\uff1a\u65e0\u9700\u670d\u52a1\u5668<\/p>\n<p>\ud83d\udc4e \u7f3a\u70b9\uff1a\u4e0d\u7075\u6d3b\uff0c\u53ea\u9002\u5408\u5c11\u91cf\u955c\u50cf\u4e0b\u8f7d\u573a\u666f<\/p>\n<h3 id=\"\u65b9\u6cd52-\u4ee3\u7406\u8fde\u63a5\">\u65b9\u6cd52\uff1a\u4ee3\u7406\u8fde\u63a5<\/h3>\n<p>\u4ee3\u7406\u670d\u52a1\u7aef\u5177\u4f53\u5b89\u88c5\u6b65\u9aa4\u7565\uff0c\u5927\u5bb6\u81ea\u884c\u7814\u7a76\u3002<\/p>\n<p>\u90e8\u7f72\u5b8c\u4ee3\u7406\u670d\u52a1\u5668\uff0c\u53ea\u9700\u8981\u7ed9Docker\u914d\u7f6e\u4e0a\u4ee3\u7406\u94fe\u63a5\u5373\u53ef<\/p>\n<p>1.\u7f16\u8f91\u914d\u7f6e\u6587\u4ef6\u00a0<code>\/lib\/systemd\/system\/docker.service<\/code>\u00a0\uff0c\u8bbe\u7f6e\u4ee3\u7406\u5730\u5740<\/p>\n<div class=\"code-toolbar\">\n<pre class=\"line-numbers language-shell\" tabindex=\"0\"><code class=\"language-shell\"><span class=\"token comment\"># \u5728[Service]\u6a21\u5757\u4e0b\u6dfb\u52a0<\/span>\r\n<span class=\"token assign-left variable\">Environment<\/span><span class=\"token operator\">=<\/span>HTTP_PROXY<span class=\"token operator\">=<\/span>http:\/\/proxyAddress:port\r\n<span class=\"token assign-left variable\">Environment<\/span><span class=\"token operator\">=<\/span>HTTPS_PROXY<span class=\"token operator\">=<\/span>http:\/\/proxyAddress:port\r\n<span class=\"token assign-left variable\">Environment<\/span><span class=\"token operator\">=<\/span>NO_PROXY<span class=\"token operator\">=<\/span>localhost,127.0.0.1\r\n<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><\/div>\n<\/div>\n<\/div>\n<p><img decoding=\"async\" src=\"https:\/\/image.4xx.me\/4xx\/2024\/06\/11\/image.png?x=f:webp\" alt=\"image.png\" \/><\/p>\n<p>2.\u91cd\u542fDocker<\/p>\n<div class=\"code-toolbar\">\n<pre class=\"line-numbers language-shell\" tabindex=\"0\"><code class=\"language-shell\"><span class=\"token function\">sudo<\/span> systemctl daemon-reload\r\n<span class=\"token function\">sudo<\/span> systemctl restart <span class=\"token function\">docker<\/span>\r\n<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><\/div>\n<\/div>\n<\/div>\n<p>\ud83d\udc4d \u4f18\u70b9\uff1a\u4e4b\u540e\u62c9\u53d6\u955c\u50cf\u8d70\u4ee3\u7406\uff0c\u4e00\u52b3\u6c38\u9038<\/p>\n<p>\ud83d\udc4e \u7f3a\u70b9\uff1a\u9700\u5883\u5916\u670d\u52a1\u5668\uff0c\u5bb9\u5668\u5185\u53ef\u80fd\u4e5f\u4f1a\u8d70\u4ee3\u7406<\/p>\n<h3 id=\"\u65b9\u6cd53-\u81ea\u5efaDocker\u52a0\u901f\u5668\">\u65b9\u6cd53\uff1a\u81ea\u5efaDocker\u52a0\u901f\u5668<\/h3>\n<p>\u6559\u7a0b1\uff1a<a href=\"https:\/\/mirrors.ustc.edu.cn\/help\/dockerhub.html\">https:\/\/mirrors.ustc.edu.cn\/help\/dockerhub.html<\/a><\/p>\n<p>\u6559\u7a0b2\uff1a<a href=\"https:\/\/github.com\/stilleshan\/dockerfiles\/tree\/main\/registry-proxy\">https:\/\/github.com\/stilleshan\/dockerfiles\/tree\/main\/registry-proxy<\/a><\/p>\n<p>\u6211\u53c2\u8003\u7684\u6559\u7a0b2\uff0c\u4e00\u4e2a\u5bb9\u5668\u641e\u5b9a\u3002<\/p>\n<p>1.\u5728\u5883\u5916\u673a\u5668\u4e0a\u642d\u5efa\u52a0\u901f\u5668\uff0c\u6211\u8fd9\u91cc\u6ca1\u6709\u6302\u8f7d\u5b58\u50a8\u51fa\u6765\uff0c\u91cd\u542f\u5373\u53ef\u6e05\u7406\u78c1\u76d8\uff0c\u66f4\u65b9\u4fbf<\/p>\n<div class=\"code-toolbar\">\n<pre class=\"line-numbers language-shell\" tabindex=\"0\"><code class=\"language-shell\"><span class=\"token function\">docker<\/span> run <span class=\"token parameter variable\">-d<\/span> <span class=\"token parameter variable\">--restart<\/span> always <span class=\"token punctuation\">\\<\/span>\r\n    <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">5000<\/span>:5000 <span class=\"token punctuation\">\\<\/span>\r\n    <span class=\"token parameter variable\">-e<\/span> <span class=\"token assign-left variable\">PROXY_REMOTE_URL<\/span><span class=\"token operator\">=<\/span>https:\/\/registry-1.docker.io <span class=\"token punctuation\">\\<\/span>\r\n    stilleshan\/registry-proxy\r\n<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><\/div>\n<\/div>\n<\/div>\n<p>2.\u5883\u5185\u673a\u5668\u4e0a\u914d\u7f6e\u52a0\u901f\u5730\u5740\uff0c\u548c\u4e4b\u524d\u4e00\u6837<\/p>\n<div class=\"code-toolbar\">\n<pre class=\"line-numbers language-shell\" tabindex=\"0\"><code class=\"language-shell\"><span class=\"token comment\"># \u7f16\u8f91 \/etc\/docker\/daemon.json\uff0c\u52a0\u5165\u5730\u5740<\/span>\r\n\r\n<span class=\"token punctuation\">{<\/span>\r\n  <span class=\"token string\">\"registry-mirrors\"<\/span><span class=\"token builtin class-name\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"http:\/\/xxxxxxx:5000\"<\/span><span class=\"token punctuation\">]<\/span>\r\n<span class=\"token punctuation\">}<\/span>\r\n<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><\/div>\n<\/div>\n<\/div>\n<p>\ud83d\udc4d \u4f18\u70b9\uff1a\u6362\u4e2a\u52a0\u901f\u5668\u5373\u53ef<\/p>\n<p>\ud83d\udc4e \u7f3a\u70b9\uff1a\u9700\u5883\u5916\u670d\u52a1\u5668<\/p>\n<h3>\u65b9\u6cd54\uff1aCloudFlare Workers\u642d\u5efaDocker\u955c\u50cf\u52a0\u901f\u5668<\/h3>\n<pre>\u57fa\u4e8e<a href=\"https:\/\/www.nodeseek.com\/jump?to=https%3A%2F%2Fv2ex.com%2Ft%2F1007922\" target=\"_blank\" rel=\"noopener\">V2EX \u7528 cloudflare worker \u642d\u5efa\u4e00\u4e2a Docker \u955c\u50cf<\/a><\/pre>\n<blockquote><p>\u4f18\u5316\u4e86\u4e00\u70b9\u70b9&#8230;<\/p><\/blockquote>\n<ul>\n<li>\u5220\u9664\u4e86\u8fd4\u56de\u5934\u4e2d\u7684<code>Docker-Distribution-Api-VersionDocker-Distribution-Api-Version<\/code>\u7279\u5f81,\u907f\u514d\u7a7a\u95f4\u6d4b\u7ed8\u5f15\u64ce\u626b\u63cf\u5230<\/li>\n<li><code>404<\/code>\u72b6\u6001\u65f6,\u8fd4\u56de\u7a7a\u5b57\u7b26,\u8fdb\u4e00\u6b65\u907f\u514d\u7279\u5f81\u626b\u63cf<\/li>\n<\/ul>\n<p>\u4f7f\u7528\u65b9\u6cd5:<\/p>\n<ul>\n<li>\u76f4\u63a5\u4fee\u6539\u5168\u5c40\u955c\u50cf\u5730\u5740: \u4fee\u6539\u6216\u521b\u5efa<code>\/etc\/docker\/daemon.json<\/code>\u5199\u5165\u4ee5\u4e0b\u5185\u5bb9\n<pre><code class=\"language-json\">{\r\n\t\"registry-mirrors\": [ \"https:\/\/\u81ea\u5b9a\u4e49\u57df\u540d\" ]\r\n}\r\n<\/code><\/pre>\n<p><img decoding=\"async\" class=\"\" src=\"https:\/\/openai-75050.gzc.vod.tencent-cloud.com\/openaiassets_b70c097737e579533b8ce10ce08cc291_2579861718099507192.png\" alt=\"\u4f7f\u7528\u65b9\u6cd5\" \/><\/li>\n<li>\u624b\u52a8\u62c9\u53d6\u5355\u4e2a\u955c\u50cf\n<pre><code class=\"language-bash\">docker pull \u57df\u540d\/ubuntu\r\n<\/code><\/pre>\n<\/li>\n<li>\u642d\u5efa\u65f6,\u5c06<code>\u81ea\u5b9a\u4e49\u5b50\u57df\u540d<\/code>\u4fee\u6539\u4e3aWorkers\u8bbe\u7f6e\u4e2d\u7684\u81ea\u5b9a\u4e49\u57df\u540d<\/li>\n<li><strong>\u5fc5\u987b\u6dfb\u52a0\u81ea\u5b9a\u4e49\u57df\u540d,\u9ed8\u8ba4\u7684workers.dev\u5728\u56fd\u5185\u65e0\u6cd5\u4f7f\u7528<\/strong><\/li>\n<\/ul>\n<hr \/>\n<p>\u4ee5\u4e0b\u4e3aWorkers\u6e90\u4ee3\u7801<\/p>\n<pre><code class=\"language-javavscript\">'use strict'\r\n\r\nconst hub_host = 'registry-1.docker.io'\r\nconst auth_url = 'https:\/\/auth.docker.io'\r\nconst workers_url = 'https:\/\/\u81ea\u5b9a\u4e49\u57df\u540d'\r\n\/**\r\n* static files (404.html, sw.js, conf.js)\r\n*\/\r\n\r\n\/** @type {RequestInit} *\/\r\nconst PREFLIGHT_INIT = {\r\n  \/\/ status: 204,\r\n  headers: new Headers({\r\n    'access-control-allow-origin': '*',\r\n    'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS',\r\n    'access-control-max-age': '1728000',\r\n  }),\r\n}\r\n\r\n\/**\r\n* @param {any} body\r\n* @param {number} status\r\n* @param {Object&lt;string, string&gt;} headers\r\n*\/\r\nfunction makeRes(body, status = 200, headers = {}) {\r\n  headers['access-control-allow-origin'] = '*'\r\n  return new Response(body, { status, headers })\r\n}\r\n\r\n\r\n\/**\r\n* @param {string} urlStr\r\n*\/\r\nfunction newUrl(urlStr) {\r\n  try {\r\n    return new URL(urlStr)\r\n  } catch (err) {\r\n    return null\r\n  }\r\n}\r\n\r\n\r\naddEventListener('fetch', e =&gt; {\r\n  const ret = fetchHandler(e)\r\n    .catch(err =&gt; makeRes('error: ' + err.stack + \"\\n\", 502))\r\n  e.respondWith(ret)\r\n})\r\n\r\n\r\n\/**\r\n* @param {FetchEvent} e\r\n*\/\r\nasync function fetchHandler(e) {\r\n  const getReqHeader = (key) =&gt; e.request.headers.get(key);\r\n\r\n  let url = new URL(e.request.url);\r\n\r\n  \/\/ \u4fee\u6539 pre head get \u8bf7\u6c42\r\n  \/\/ \u662f\u5426\u542b\u6709 %2F \uff0c\u7528\u4e8e\u5224\u65ad\u662f\u5426\u5177\u6709\u7528\u6237\u540d\u4e0e\u4ed3\u5e93\u540d\u4e4b\u95f4\u7684\u8fde\u63a5\u7b26\r\n  \/\/ \u540c\u65f6\u68c0\u67e5 %3A \u7684\u5b58\u5728\r\n  if (!\/%2F\/.test(url.search) &amp;&amp; \/%3A\/.test(url.toString())) {\r\n    let modifiedUrl = url.toString().replace(\/%3A(?=.*?&amp;)\/, '%3Alibrary%2F');\r\n    url = new URL(modifiedUrl);\r\n    console.log(`handle_url: ${url}`)\r\n  }\r\n\r\n  if (url.pathname === '\/token') {\r\n    let token_parameter = {\r\n      headers: {\r\n        'Host': 'auth.docker.io',\r\n        'User-Agent': getReqHeader(\"User-Agent\"),\r\n        'Accept': getReqHeader(\"Accept\"),\r\n        'Accept-Language': getReqHeader(\"Accept-Language\"),\r\n        'Accept-Encoding': getReqHeader(\"Accept-Encoding\"),\r\n        'Connection': 'keep-alive',\r\n        'Cache-Control': 'max-age=0'\r\n      }\r\n    };\r\n    let token_url = auth_url + url.pathname + url.search\r\n    return fetch(new Request(token_url, e.request), token_parameter)\r\n  }\r\n\r\n  \/\/ \u4fee\u6539 head \u8bf7\u6c42\r\n  if (\/^\\\/v2\\\/[^\/]+\\\/[^\/]+\\\/[^\/]+$\/.test(url.pathname) &amp;&amp; !\/^\\\/v2\\\/library\/.test(url.pathname)) {\r\n    url.pathname = url.pathname.replace(\/\\\/v2\\\/\/, '\/v2\/library\/');\r\n    console.log(`modified_url: ${url.pathname}`)\r\n  }\r\n\r\n  url.hostname = hub_host;\r\n\r\n  let parameter = {\r\n    headers: {\r\n      'Host': hub_host,\r\n      'User-Agent': getReqHeader(\"User-Agent\"),\r\n      'Accept': getReqHeader(\"Accept\"),\r\n      'Accept-Language': getReqHeader(\"Accept-Language\"),\r\n      'Accept-Encoding': getReqHeader(\"Accept-Encoding\"),\r\n      'Connection': 'keep-alive',\r\n      'Cache-Control': 'max-age=0'\r\n    },\r\n    cacheTtl: 3600\r\n  };\r\n\r\n  if (e.request.headers.has(\"Authorization\")) {\r\n    parameter.headers.Authorization = getReqHeader(\"Authorization\");\r\n  }\r\n\r\n  let original_response = await fetch(new Request(url, e.request), parameter)\r\n  let original_response_clone = original_response.clone();\r\n  let original_text = original_response_clone.body;\r\n  let response_headers = original_response.headers;\r\n  let new_response_headers = new Headers(response_headers);\r\n  let status = original_response.status;\r\n\r\n  if (new_response_headers.get(\"Www-Authenticate\")) {\r\n    let auth = new_response_headers.get(\"Www-Authenticate\");\r\n    let re = new RegExp(auth_url, 'g');\r\n    new_response_headers.set(\"Www-Authenticate\", response_headers.get(\"Www-Authenticate\").replace(re, workers_url));\r\n  }\r\n  if (new_response_headers.get(\"Docker-Distribution-Api-Version\")){\r\n    new_response_headers.delete(\"Docker-Distribution-Api-Version\");\r\n  }\r\n\r\n  if (new_response_headers.get(\"Location\")) {\r\n    return httpHandler(e.request, new_response_headers.get(\"Location\"))\r\n  }\r\n  if (status === 404){\r\n    original_text = \"\";\r\n  }\r\n  let response = new Response(original_text, {\r\n    status,\r\n    headers: new_response_headers\r\n  })\r\n  return response;\r\n\r\n}\r\n\r\n\r\n\/**\r\n* @param {Request} req\r\n* @param {string} pathname\r\n*\/\r\nfunction httpHandler(req, pathname) {\r\n  const reqHdrRaw = req.headers\r\n\r\n  \/\/ preflight\r\n  if (req.method === 'OPTIONS' &amp;&amp;\r\n    reqHdrRaw.has('access-control-request-headers')\r\n  ) {\r\n    return new Response(null, PREFLIGHT_INIT)\r\n  }\r\n\r\n  let rawLen = ''\r\n\r\n  const reqHdrNew = new Headers(reqHdrRaw)\r\n\r\n  const refer = reqHdrNew.get('referer')\r\n\r\n  let urlStr = pathname\r\n\r\n  const urlObj = newUrl(urlStr)\r\n\r\n  \/** @type {RequestInit} *\/\r\n  const reqInit = {\r\n    method: req.method,\r\n    headers: reqHdrNew,\r\n    redirect: 'follow',\r\n    body: req.body\r\n  }\r\n  return proxy(urlObj, reqInit, rawLen)\r\n}\r\n\r\n\r\n\/**\r\n*\r\n* @param {URL} urlObj\r\n* @param {RequestInit} reqInit\r\n*\/\r\nasync function proxy(urlObj, reqInit, rawLen) {\r\n  const res = await fetch(urlObj.href, reqInit)\r\n  const resHdrOld = res.headers\r\n  const resHdrNew = new Headers(resHdrOld)\r\n\r\n  \/\/ verify\r\n  if (rawLen) {\r\n    const newLen = resHdrOld.get('content-length') || ''\r\n    const badLen = (rawLen !== newLen)\r\n\r\n    if (badLen) {\r\n      return makeRes(res.body, 400, {\r\n        '--error': `bad len: ${newLen}, except: ${rawLen}`,\r\n        'access-control-expose-headers': '--error',\r\n      })\r\n    }\r\n  }\r\n  const status = res.status\r\n  resHdrNew.set('access-control-expose-headers', '*')\r\n  resHdrNew.set('access-control-allow-origin', '*')\r\n  resHdrNew.set('Cache-Control', 'max-age=1500')\r\n\r\n  resHdrNew.delete('content-security-policy')\r\n  resHdrNew.delete('content-security-policy-report-only')\r\n  resHdrNew.delete('clear-site-data')\r\n\r\n  return new Response(res.body, {\r\n    status,\r\n    headers: resHdrNew\r\n  })\r\n}<\/code><\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u65b9\u6cd51\uff1a\u955c\u50cf\u8f6c\u5b58 \u501f\u52a9Github\u548c\u963f\u91cc\u4e91\u955c\u50cf\u4ed3\u5e93\uff0c\u8f6c\u5b58\u955c\u50cf\u3002 \u5177\u4f53\u65b9\u6cd5\u53c2\u8003\uff1ahttps:\/\/www.bili [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":530,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[100],"tags":[121],"class_list":["post-528","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-100","tag-docker"],"_links":{"self":[{"href":"https:\/\/sharebits.link\/index.php?rest_route=\/wp\/v2\/posts\/528","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sharebits.link\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sharebits.link\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sharebits.link\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sharebits.link\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=528"}],"version-history":[{"count":0,"href":"https:\/\/sharebits.link\/index.php?rest_route=\/wp\/v2\/posts\/528\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sharebits.link\/index.php?rest_route=\/wp\/v2\/media\/530"}],"wp:attachment":[{"href":"https:\/\/sharebits.link\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=528"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sharebits.link\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=528"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sharebits.link\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=528"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}