Docker Hub Mirrors

Show other mirrors to pull current docker image.

  1. // ==UserScript==
  2. // @name Docker Hub Mirrors
  3. // @namespace https://github.com/iamspark1e/my-tampermonkey-scripts/blob/main/docker-mirror-urls.js
  4. // @version 0.1.1
  5. // @description Show other mirrors to pull current docker image.
  6. // @author iamspark1e
  7. // @license AGPL-3.0-or-later
  8. // @match *://hub.docker.com/_/*
  9. // @match *://hub.docker.com/r/*
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // ==/UserScript==
  13.  
  14. // ref: https://juejin.cn/post/7022654292880424991
  15. // - 阿里云(杭州) https://registry.cn-hangzhou.aliyuncs.com
  16. // - 阿里云(上海) https://registry.cn-shanghai.aliyuncs.com
  17. // - 阿里云(青岛) https://registry.cn-qingdao.aliyuncs.com
  18. // - 阿里云(北京) https://registry.cn-beijing.aliyuncs.com
  19. // - 阿里云(张家口) https://registry.cn-zhangjiakou.aliyuncs.com
  20. // - 阿里云(呼和浩特) https://registry.cn-huhehaote.aliyuncs.com
  21. // - 阿里云(乌兰察布) https://registry.cn-wulanchabu.aliyuncs.com
  22. // - 阿里云(深圳) https://registry.cn-shenzhen.aliyuncs.com
  23. // - 阿里云(河源) https://registry.cn-heyuan.aliyuncs.com
  24. // - 阿里云(广州) https://registry.cn-guangzhou.aliyuncs.com
  25. // - 阿里云(成都) https://registry.cn-chengdu.aliyuncs.com
  26. // - 腾讯云 https://mirror.ccs.tencentyun.com
  27. // - 微软云 https://dockerhub.azk8s.com
  28. // - 网易 https://hub-mirror.c.163.com
  29. // - 上海交通大学 https://mirror.sjtu.edu.cn/docs/docker-registry
  30. // - ❤❤❤南京大学 https://docker.nju.edu.cn
  31. // - 道客 DaoCloud https://f1361db2.m.daocloud.io
  32. // - 阿里云(香港) https://registry.cn-hongkong.aliyuncs.com
  33. // - 阿里云(日本-东京) https://registry.ap-northeast-1.aliyuncs.com
  34. // - 阿里云(新加坡) https://registry.ap-southeast-1.aliyuncs.com
  35. // - 阿里云(澳大利亚-悉尼) https://registry.ap-southeast-2.aliyuncs.com
  36. // - 阿里云(马来西亚-吉隆坡) https://registry.ap-southeast-3.aliyuncs.com
  37. // - 阿里云(印度尼西亚-雅加达) https://registry.ap-southeast-5.aliyuncs.com
  38. // - 阿里云(印度-孟买) https://registry.ap-south-1.aliyuncs.com
  39. // - 阿里云(德国-法兰克福) https://registry.eu-central-1.aliyuncs.com
  40. // - 阿里云(英国-伦敦) https://registry.eu-west-1.aliyuncs.com
  41. // - 阿里云(美国西部-硅谷) https://registry.us-west-1.aliyuncs.com
  42. // - 阿里云(美国东部-弗吉尼亚) https://registry.us-east-1.aliyuncs.com
  43. // - 阿里云(阿联酋-迪拜) https://registry.me-east-1.aliyuncs.com
  44. // - 谷歌云 https://gcr.io
  45. // - 官方 https://registry.hub.docker.com
  46.  
  47. (function () {
  48. 'use strict';
  49. const ALTER_HUBS = [
  50. { "url": "registry.cn-hangzhou.aliyuncs.com", "name": "阿里云(杭州)" },
  51. { "url": "mirror.ccs.tencentyun.com", "name": "腾讯云" },
  52. { "url": "dockerhub.azk8s.com", "name": "微软云(Azure)" },
  53. { "url": "hub-mirror.c.163.com", "name": "网易" },
  54. { "url": "mirror.sjtu.edu.cn/docs/docker-registry", "name": "上海交通大学" },
  55. { "url": "docker.nju.edu.cn", "name": "南京大学" },
  56. { "url": "f1361db2.m.daocloud.io", "name": "DaoCloud" },
  57. { "url": "gcr.io", "name": "Google" },
  58. { "url": "registry.hub.docker.com", "name": "官方" },
  59. ]
  60. const DOM_IDENTIFIER = "iamspark1e_tampermonkey_docker_mirror_helper"
  61. const DOM_TPL = `
  62. <label>
  63. <span>Choose a mirror: </span>
  64. <select>
  65. ${ALTER_HUBS.map(hub => `<option value="${hub.url}">${hub.name}</option>`).join("")}
  66. </select>
  67. </label>
  68. <div class="show_url" style="background-color:rgba(255,255,255,0.3);border-radius:4px;margin-top:4px;padding:4px;"></div>
  69. `
  70.  
  71. const GENERATE_SNIPPETS = (hub, image_name) => `
  72. <p>URL: <span style="user-select:all;word-break:break-all;">${hub.url + '/' + image_name}</span></p>
  73. <p>Docker pull: <code style="user-select:all;word-break:break-all;">docker pull ${hub.url + '/' + image_name}</code></p>
  74. `
  75.  
  76. let siblingNode;
  77. let currentHub = ALTER_HUBS[0];
  78. let imageFullName;
  79. let oldHref = window.location.href;
  80.  
  81. function renderUrls() {
  82. let dom = document.querySelector(`#${DOM_IDENTIFIER} div.show_url`);
  83. dom.innerHTML = GENERATE_SNIPPETS(currentHub, imageFullName)
  84. }
  85. function selectHandler(e) {
  86. currentHub = ALTER_HUBS.find(hub => hub.url === e.target.value);
  87. renderUrls();
  88. }
  89.  
  90. function initHelper() {
  91. if (!siblingNode) {
  92. console.error("no siblingNode, init failed");
  93. return;
  94. }
  95. const mountNode = siblingNode.parentNode.parentNode;
  96. imageFullName = siblingNode.innerText.replace("docker pull ", "");
  97.  
  98. if (!document.querySelector(`#${DOM_IDENTIFIER}`)) {
  99. const testDiv = document.createElement("div")
  100. testDiv.setAttribute("style", "border:1px solid #c4c8d1;background-color: #e1e2e6;border-radius: 4px;padding:8px;margin-top: 8px;");
  101. testDiv.id = DOM_IDENTIFIER;
  102. testDiv.innerHTML = DOM_TPL;
  103. mountNode.appendChild(testDiv);
  104.  
  105. // addEventListener
  106. const selector = document.querySelector(`#${DOM_IDENTIFIER} select`);
  107. selector.addEventListener("change", selectHandler);
  108. renderUrls();
  109. }
  110. }
  111.  
  112. let observer = new MutationObserver((mutationList, observer) => {
  113. if(oldHref !== window.location.href) {
  114. siblingNode = null;
  115. oldHref = window.location.href;
  116. }
  117. for (const mutation of mutationList) {
  118. if (mutation.type === "childList" && !siblingNode) {
  119. const tmp = document.querySelector('code[data-testid="copyPullCommandPullCommand"]')
  120. if (tmp && !siblingNode) {
  121. siblingNode = tmp;
  122. initHelper();
  123. // observer.disconnect()
  124. }
  125. }
  126. }
  127. });
  128. // *://hub.docker.com/_/*
  129. // *://hub.docker.com/r/*
  130. observer.observe(document.body, {
  131. childList: true,
  132. subtree: true
  133. })
  134.  
  135.  
  136.  
  137. // TODO:
  138. // *://hub.docker.com/_/*/tags
  139. // *://hub.docker.com/r/*/tags
  140. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址