[
  {
    "path": ".gitee/ISSUE_TEMPLATE/allows-image.yml",
    "content": "name: Allows Image\ndescription: 添加白名单 (人工审核)\nlabels:\n- allows image\nbody:\n- type: markdown\n  attributes:\n    value: |\n      - 对于镜像的要求 [#2328](https://github.com/DaoCloud/public-image-mirror/issues/2328)\n      - 一般 5个工作日内 🐢 [查看成功案例](https://github.com/DaoCloud/public-image-mirror/issues?q=is%3Aissue+label%3A%22allows+image%22+is%3Aclosed+linked%3Apr)\n      - 自己提 [PR](https://github.com/DaoCloud/public-image-mirror/blob/main/allows.txt) 修改白名单优先审查 🚀\n      - 注意在 PR 的内容里描述 Fixed # 这个 issue 的 id [示例](https://github.com/DaoCloud/public-image-mirror/pull/23762)\n\n- type: dropdown\n  attributes:\n    label: 白名单级别\n    options:\n    - 只需要这一个镜像 (如 docker.io/library/busybox)\n    - 需要这个组织下所有镜像 (如 docker.io/library/*)\n  validations:\n    required: true\n\n- type: textarea\n  attributes:\n    label: 镜像仓库地址\n    placeholder: |\n      https://hub.docker.com/r/...\n  validations:\n    required: true\n\n- type: dropdown\n  attributes:\n    label: 这是 **镜像仓库** 认证可信的 **验证过的发布者(Verified Publisher)**或者**赞助的项目(Sponsored OSS)** 么?\n    options:\n    - 不是 - 请补充下面的信息\n    - 是的 - 不需要填下面的信息 - 如果实际上不是将不再继续核查\n  validations:\n    required: true\n\n- type: textarea\n  attributes:\n    label: 项目源码地址 或 组织地址\n    placeholder: |\n      https://github.com/...\n\n- type: textarea\n  attributes:\n    label: 官网 或 文档 或 项目源码 中哪提及对应的镜像的地址 (需要证明这个镜像和源码有实际关联)\n\n- type: textarea\n  attributes:\n    label: 补充说明\n\n- type: markdown\n  attributes:\n    value: |\n      有疑问反馈, 请添加我们的企微群 [#4183](https://github.com/DaoCloud/public-image-mirror/issues/4183)\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/allows-image.yml",
    "content": "name: Allows Image\ndescription: 添加白名单 (人工审核)\nlabels:\n- allows image\nbody:\n- type: markdown\n  attributes:\n    value: |\n      - 对于镜像的要求 [#2328](https://github.com/DaoCloud/public-image-mirror/issues/2328)\n      - 一般 5个工作日内 🐢 [查看成功案例](https://github.com/DaoCloud/public-image-mirror/issues?q=is%3Aissue+label%3A%22allows+image%22+is%3Aclosed+linked%3Apr)\n      - 自己提 [PR](https://github.com/DaoCloud/public-image-mirror/blob/main/allows.txt) 修改白名单优先审查 🚀\n      - 注意在 PR 的内容里描述 Fixed # 这个 issue 的 id [示例](https://github.com/DaoCloud/public-image-mirror/pull/23762)\n\n- type: dropdown\n  attributes:\n    label: 白名单级别\n    options:\n    - 只需要这一个镜像 (如 docker.io/library/busybox)\n    - 需要这个组织下所有镜像 (如 docker.io/library/*)\n  validations:\n    required: true\n\n- type: textarea\n  attributes:\n    label: 镜像仓库地址\n    placeholder: |\n      https://hub.docker.com/r/...\n  validations:\n    required: true\n\n- type: dropdown\n  attributes:\n    label: 这是 **镜像仓库** 认证可信的 **验证过的发布者(Verified Publisher)**或者**赞助的项目(Sponsored OSS)** 么?\n    options:\n    - 不是 - 请补充下面的信息\n    - 是的 - 不需要填下面的信息 - 如果实际上不是将不再继续核查\n  validations:\n    required: true\n\n- type: textarea\n  attributes:\n    label: 项目源码地址 或 组织地址\n    placeholder: |\n      https://github.com/...\n\n- type: textarea\n  attributes:\n    label: 官网 或 文档 或 项目源码 中哪提及对应的镜像的地址 (需要证明这个镜像和源码有实际关联)\n\n- type: textarea\n  attributes:\n    label: 补充说明\n\n- type: markdown\n  attributes:\n    value: |\n      有疑问反馈, 请添加我们的企微群 [#4183](https://github.com/DaoCloud/public-image-mirror/issues/4183)\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/sync-image.yml",
    "content": "name: Sync Image\ndescription: 同步一个镜像 (需要 Image 已在白名单里)\nlabels:\n- sync image\nbody:\n- type: markdown\n  attributes:\n    value: |\n      # ↑↑↑↑↑↑↑↑↑↑↑ 填入你要同步的 Image\n      ## 请包含 域名/路径:标签\n\n- type: dropdown\n  attributes:\n    label: 镜像架构\n    description: 请选择要同步的目标架构\n    options:\n    - linux/amd64\n    - linux/386\n    - linux/arm64\n    - linux/arm/v6\n    - linux/arm/v7\n    - linux/ppc64le\n    - linux/s390x\n  validations:\n    required: true\n\n- type: markdown\n  attributes:\n    value: |\n      请确保包含域名(domain)\n      - 如 docker.io/\n      - 如 registry.k8s.io/\n      - 如果不包含域名, 需要主动添加默认的 docker.io/\n\n- type: markdown\n  attributes:\n    value: |\n      请确保包含镜像的标签(tag)\n      - 如 :latest\n      - 如 :v1\n\n- type: markdown\n  attributes:\n    value: |\n      请确保这个镜像真实存在\n      - 如 docker.io/library/busybox:latest\n      - 如 docker.io/kindest/node:v1.30.0\n      - 如 registry.k8s.io/kubectl:v1.30.0\n\n- type: markdown\n  attributes:\n    value: |\n      有疑问反馈, 请添加我们的企微群 [#4183](https://github.com/DaoCloud/public-image-mirror/issues/4183)\n"
  },
  {
    "path": ".github/workflows/ci-bot.yml",
    "content": "name: CI Bot\non:\n  issue_comment:\n    types:\n      - created\n\n  pull_request_review_comment:\n    types:\n      - created\n\n  issues:\n    types:\n      - opened\n\n  # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target\n  pull_request_target:\n    types:\n      - opened\n\nenv:\n  # This plugins is for anyone who can use it\n  PLUGINS: |-\n    assign\n    auto-cc\n    cc\n\n  # This plugins is for author of issue or PR\n  AUTHOR_PLUGINS: |-\n    label-bug\n    label-documentation\n    label-enhancement\n    label-question\n    retest\n\n  # This plugins is for organization member or repository member\n  MEMBERS_PLUGINS: |-\n    label-duplicate\n    label-good-first-issue\n    label-help-wanted\n    label-invalid\n    label-kind\n    label-wontfix\n    label-bug\n    label-documentation\n    label-enhancement\n    label-question\n    lifecycle\n    retest\n\n  # This plugins is for in the REVIEWERS environment variable\n  REVIEWERS_PLUGINS: |-\n    label-lgtm\n    retitle\n\n  # This plugins is for in the APPROVERS environment variable\n  APPROVERS_PLUGINS: |-\n    label\n    merge\n    base\n    rebase\n\n  # This plugins is for in the MAINTAINERS environment variable\n  MAINTAINERS_PLUGINS: |-\n    milestone\n\n  # This plugins is for organization owner or repository owner\n  OWNERS_PLUGINS: \"\"\n\n  REVIEWERS: |-\n    yankay\n    wzshiming\n  APPROVERS: |-\n    yankay\n    wzshiming\n  MAINTAINERS: |-\n    yankay\n    wzshiming\n\n  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n  GH_REPOSITORY: ${{ github.repository }}\n  DETAILS: |-\n\n    <details>\n    <summary>Details</summary>\n\n    Instructions for interacting with me using comments are available here.\n    If you have questions or suggestions related to my behavior, please file an issue against the [gh-ci-bot](https://github.com/wzshiming/gh-ci-bot) repository.\n\n    </details>\n\n# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token\npermissions:\n  actions: write\n  checks: read\n  contents: write\n  deployments: none\n  id-token: none\n  issues: write\n  discussions: read\n  packages: none\n  pages: none\n  pull-requests: write\n  repository-projects: read\n  security-events: none\n  statuses: read\n\njobs:\n  bot:\n    name: Bot\n    runs-on: ubuntu-latest\n    steps:\n      - name: Issue Opened\n        uses: wzshiming/gh-ci-bot@v1\n        if: ${{ github.event_name == 'issues' }}\n        env:\n          LOGIN: ${{ github.event.issue.user.login }}\n          AUTHOR: ${{ github.event.issue.user.login }}\n          MESSAGE: ${{ github.event.issue.body }}\n          ISSUE_NUMBER: ${{ github.event.issue.number }}\n          AUTHOR_ASSOCIATION: ${{ github.event.issue.author_association }}\n          ISSUE_KIND: issue\n          TYPE: created\n          GREETING: |-\n            Hi @${{ github.event.issue.user.login }},\n            感谢您的反馈!\n            我们会尽快跟进.\n\n      - name: PR Opened\n        uses: wzshiming/gh-ci-bot@v1\n        if: ${{ github.event_name == 'pull_request_target' }}\n        env:\n          LOGIN: ${{ github.event.pull_request.user.login }}\n          AUTHOR: ${{ github.event.pull_request.user.login }}\n          MESSAGE: ${{ github.event.pull_request.body }}\n          ISSUE_NUMBER: ${{ github.event.pull_request.number }}\n          AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association }}\n          ISSUE_KIND: pr\n          TYPE: created\n          GREETING: |-\n            Hi @${{ github.event.pull_request.user.login }},\n            感谢您的 PR !\n            如果 PR 已经准备就绪可以 `/auto-cc` ,我们会尽快跟进.\n\n      - name: Issue Commented\n        uses: wzshiming/gh-ci-bot@v1\n        if: ${{ github.event_name == 'issue_comment' && !github.event.issue.pull_request }}\n        env:\n          LOGIN: ${{ github.event.comment.user.login }}\n          AUTHOR: ${{ github.event.issue.user.login }}\n          MESSAGE: ${{ github.event.comment.body }}\n          ISSUE_NUMBER: ${{ github.event.issue.number }}\n          AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}\n          ISSUE_KIND: issue\n          TYPE: comment\n\n      - name: PR Review Commented\n        uses: wzshiming/gh-ci-bot@v1\n        if: ${{ github.event_name == 'pull_request_review_comment' }}\n        env:\n          LOGIN: ${{ github.event.comment.user.login }}\n          AUTHOR: ${{ github.event.pull_request.user.login }}\n          MESSAGE: ${{ github.event.comment.body }}\n          ISSUE_NUMBER: ${{ github.event.pull_request.number }}\n          AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}\n          ISSUE_KIND: pr\n          TYPE: comment\n\n      - name: PR Commented\n        uses: wzshiming/gh-ci-bot@v1\n        if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request }}\n        env:\n          LOGIN: ${{ github.event.comment.user.login }}\n          AUTHOR: ${{ github.event.issue.user.login }}\n          MESSAGE: ${{ github.event.comment.body }}\n          ISSUE_NUMBER: ${{ github.event.issue.number }}\n          AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}\n          ISSUE_KIND: pr\n          TYPE: comment\n"
  },
  {
    "path": ".github/workflows/cidn-runner.yml",
    "content": "name: CIDN Runner\nrun-name: CIDN Runner ${{ github.run_number }}\n\non:\n  schedule:\n    - cron: \"0,30 * * * *\"\n\n  workflow_dispatch:\n\njobs:\n  runner:\n    runs-on: ubuntu-latest\n    if: github.repository == 'DaoCloud/public-image-mirror'\n    container: ghcr.io/opencidn/cidn/runner:v0.0.109\n    steps:\n    - shell: sh\n      run: runner --handler-name=dc-${{ github.run_number }} --update-duration=10s --duration=4h --concurrency=3 ${{ secrets.ARGS_CIDN }}\n"
  },
  {
    "path": ".github/workflows/sync-image.yml",
    "content": "name: Target Sync Image\nrun-name: Target Sync ${{ github.event.issue.title }} by @${{ github.actor }}\n\non:\n  issues:\n    types:\n      - opened\n\n# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token\npermissions:\n  issues: write\n\njobs:\n  check:\n    runs-on: ubuntu-latest\n    if: contains(github.event.issue.labels.*.name, 'sync image')\n    env:\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n    outputs:\n      image: ${{ steps.get-image.outputs.image }}\n      link: ${{ steps.get-image.outputs.link }}\n      platforms: ${{ steps.get-image.outputs.platforms }}\n      arch: ${{ steps.get-image.outputs.arch }}\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v4\n    - name: Check Issue\n      id: get-image\n      env:\n        IMAGE: \"${{ github.event.issue.title }}\"\n        ISSUE_BODY: \"${{ github.event.issue.body }}\"\n      run: |\n        ORIGIN_IMAGE=\"${IMAGE}\"\n        CORRECT_IMAGE=\"$(./hack/correct-image.sh \"${ORIGIN_IMAGE}\")\"\n        if [[ \"${CORRECT_IMAGE}\" == \"\" ]]; then\n          gh issue comment ${{ github.event.issue.number }} -b \"镜像 '${ORIGIN_IMAGE}' 不是一个镜像\"\n          gh issue close ${{ github.event.issue.number }} --reason \"not planned\"\n          exit 1\n        fi\n        if [[ \"${CORRECT_IMAGE}\" != \"${ORIGIN_IMAGE}\" ]]; then\n          if ! ./hack/verify-allows.sh ./allows.txt \"${CORRECT_IMAGE}\"; then\n            gh issue comment ${{ github.event.issue.number }} -b \"镜像 '${ORIGIN_IMAGE}' 不存在呢, 也许应该是 '${CORRECT_IMAGE}', 并且不在白名单列表里, 不支持同步和访问<br>可以将其添加到[白名单](https://github.com/${{ github.repository }}/issues/2328)\"\n          else\n            gh issue comment ${{ github.event.issue.number }} -b \"镜像 '${ORIGIN_IMAGE}' 不存在呢, 也许应该是 '${CORRECT_IMAGE}'\"\n          fi\n          gh issue close ${{ github.event.issue.number }} --reason \"not planned\"\n          exit 1\n        fi\n        if ! ./hack/verify-allows.sh ./allows.txt \"${ORIGIN_IMAGE}\"; then\n          gh issue comment ${{ github.event.issue.number }} -b \"镜像 ${ORIGIN_IMAGE} 不在白名单列表里, 不支持同步和访问<br>可以将其添加到[白名单](https://github.com/${{ github.repository }}/issues/2328)\"\n          gh issue close ${{ github.event.issue.number }} --reason \"not planned\"\n          exit 1\n        fi\n\n        IMAGE=\"${ORIGIN_IMAGE}\"\n        echo \"image=${IMAGE}\" >> $GITHUB_OUTPUT\n        GROUP=\"${IMAGE%%:*}\"\n        GROUP=\"${GROUP%%@*}\"\n        LINK=\"https://queue.m.daocloud.io/status/#group:${GROUP}\"\n        echo \"link=${LINK}\" >> $GITHUB_OUTPUT\n\n        BODY=\"${ISSUE_BODY:-}\"\n        ARCH=\"\"\n\n        if [ -z \"${ARCH}\" ]; then\n          ARCH=$(printf \"%s\" \"$BODY\" | grep -oE 'linux/[a-z0-9/._+-]+' | head -n1 || true)\n        fi\n\n        if [ -z \"${ARCH}\" ]; then\n          ARCH=\"linux/amd64\"\n        fi\n\n        echo \"arch=${ARCH}\" >> $GITHUB_OUTPUT\n\n        PLATFORM_FLAG=\"--platform=${ARCH}\"\n        echo \"platforms=${PLATFORM_FLAG}\" >> $GITHUB_OUTPUT\n\n        gh issue comment ${{ github.event.issue.number }} -b \"镜像 ${IMAGE}, 平台 ${ARCH} 将添加到同步队列...<br>[同步队列](${LINK})<br>[详细信息](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})\"\n\n  sync:\n    runs-on: ubuntu-latest\n    needs: check\n    if: needs.check.result == 'success'\n    container: ghcr.io/opencidn/ocimirror/sync:v0.0.40\n    steps:\n    - shell: sh\n      run: sync ${{ needs.check.outputs.image }} ${{ needs.check.outputs.platforms }} ${{ secrets.ARGS_CIDN }} ${{ secrets.ARGS_R2_IMAGE }}\n\n  runner:\n    runs-on: ubuntu-latest\n    needs: check\n    if: needs.check.result == 'success'\n    container: ghcr.io/opencidn/cidn/runner:v0.0.108\n    steps:\n    - shell: sh\n      run: runner --handler-name=dc-${{ github.run_number }}-${{ github.event.issue.number }} --update-duration=10s --duration=5m --concurrency=2 ${{ secrets.ARGS_CIDN }}\n\n  failure:\n    runs-on: ubuntu-latest\n    needs:\n    - sync\n    - check\n    if: always() && needs.sync.result == 'failure'\n    env:\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n    steps:\n    - name: Sync Failure Status\n      run: |\n        gh -R \"${{ github.repository }}\" issue edit ${{ github.event.issue.number }} --add-label \"sync image failure\" -b \"镜像同步失败\"\n        gh -R \"${{ github.repository }}\" issue close ${{ github.event.issue.number }} --reason \"not planned\" --comment \"镜像 ${{ needs.check.outputs.image }}, 平台 ${{ needs.check.outputs.arch }} 同步失败<br>请去同步队列查看详细信息。\"\n  \n  success:\n    runs-on: ubuntu-latest\n    needs:\n    - sync\n    - check\n    if: needs.sync.result == 'success'\n    env:\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n    steps:\n    - name: Sync Success Status\n      run: |\n        gh -R \"${{ github.repository }}\" issue edit ${{ github.event.issue.number }} --add-label \"sync image succeeded\" -b \"镜像同步完成\"\n        gh -R \"${{ github.repository }}\" issue close ${{ github.event.issue.number }} --reason \"completed\" --comment \"镜像 ${{ needs.check.outputs.image }}, 平台 ${{ needs.check.outputs.arch }} 同步完成<br>请使用 m.daocloud.io/${{ needs.check.outputs.image }} 进行访问。\"\n"
  },
  {
    "path": ".github/workflows/update-allows-list.yml",
    "content": "name: Update allows list\n\non:\n  push:\n    paths:\n    - allows.txt\n    branches:\n    - main\n  workflow_dispatch:\n\njobs:\n  update-allows-list:\n    if: github.repository == 'DaoCloud/public-image-mirror'\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v4\n\n    - name: Update list\n      run: |\n        LIST=\"$(cat ./allows.txt | grep -v 'docker.io/\\*' | sed 's/docker.io\\/library\\/\\([^\\/]*\\)/&\\ndocker.io\\/\\1/' | jq -R -s -c '{\"items\": split(\"\\n\")[:-1], \"block_message\": \"🚫 👀-> https://github.com/DaoCloud/public-image-mirror/issues/2328 🔗 这镜像不在白名单. this image is not in the allowlist.\"}')\"\n        TOKEN=\"$(curl -X 'POST' \\\n          'https://queue.m.daocloud.io/apis/auth/users/login' \\\n          -H 'Accept: application/json' \\\n          -H 'Content-Type: application/json' \\\n          -d ${{ secrets.USER_LOGIN_DATA }} | jq -r .token)\"\n        curl -f -X 'PUT' \\\n          'https://queue.m.daocloud.io/apis/auth/registries/allow_images' \\\n          -H 'Accept: application/json' \\\n          -H \"Authorization: Bearer ${TOKEN}\" \\\n          -H 'Content-Type: application/json' \\\n          -d \"${LIST}\"\n"
  },
  {
    "path": ".github/workflows/verify-pr.yml",
    "content": "name: Verify PR\n\non:\n  pull_request_target:\n    branches: [main]\n    paths:\n      - 'mirror.txt'\n      - 'allows.txt'\n\npermissions:\n  issues: write\n  pull-requests: write\n\nenv:\n  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\njobs:\n  verify-pr:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Commit PR\n        run: |\n          git config --global user.name \"github-actions[bot]\"\n          git config --global user.email \"github-actions[bot]@users.noreply.github.com\"\n          wget -O pr.patch https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}.patch && \\\n            git am -3 pr.patch &&\n            rm -rf pr.patch\n\n      - name: Verify allows.txt sort\n        run: |\n          ./hack/verify-image-match.sh allows.txt || {\n            echo \"Please run './hack/fmt-image-match.sh allows.txt'\"\n            gh pr comment \"${{ github.event.pull_request.number }}\" --body '请运行 `./hack/fmt-image-match.sh allows.txt` 对内容进行排序'\n            exit 1\n          }\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# public-image-mirror\n\n源仓库 [Github](https://github.com/DaoCloud/public-image-mirror)  \nMirror 仓库 [Gitee](https://gitee.com/daocloud/public-image-mirror)  \n\n- 白名单 & 限流 的公开信息 [#2328](https://github.com/DaoCloud/public-image-mirror/issues/2328)\n- 如有疑问请咨询 [#4183](https://github.com/DaoCloud/public-image-mirror/issues/4183)\n- 建议将拉取任务放在闲时 凌晨(北京时间 01-07 点), 其他时间段非常拥挤\n- 建议使用明确版本号的 tag, 对于 latest 这种变更后响应旧数据, 并且后台重新同步\n- [本服务后端代码](https://github.com/OpenCIDN/ocimirror)\n- [同步队列](https://queue.m.daocloud.io/status/) 仅保留一小时的同步记录\n- [服务状态监控](https://status.daocloud.io/status/docker)\n\n## 背景 & 目标\n\n很多镜像都在国外。比如 gcr 。国内下载很慢，需要加速。\n\n* 一个简洁有效的方法能够加速这些包。简洁的名称映射\n* 易于添加，添加新的包，不需要去修改代码。\n* 稳定可靠，更新实时。每天检查同步情况。\n* 此项目仅是源镜像仓库 (Registry) 的 Mirror\n  * 所有 hash(sha256) 均和源保持一致 (懒加载机制)。\n  * 缓存的内容只保留 90 天, 过期后会需要重新同步。\n  * Manifest 内存缓存 1 小时, 所以 tag 被更新了 1 小时之后才会同步新的。\n  * Blob 内存缓存 1 分钟, 在期间如果 blob 到达 90 天期限被删除会报 404。\n\n## 快速开始\n\n```\ndocker run -d -P m.daocloud.io/docker.io/library/nginx\n```\n## 使用方法\n\n**增加前缀** (推荐方式)。比如：\n\n``` log\n              docker.io/library/busybox\n                 |\n                 V\nm.daocloud.io/docker.io/library/busybox\n```\n\n或者 支持的镜像仓库 的 *前缀替换* 就可以使用。比如：\n\n``` log\n           docker.io/library/busybox\n             |\n             V\ndocker.m.daocloud.io/library/busybox\n```\n\n## 支持前缀替换的 Registry (不推荐)\n\n推荐使用添加前缀的方式.\n\n前缀替换的 Registry 的规则, 这是人工配置的, 有需求提 Issue.\n\n除了 docker.io 这里每一个源站, 内容都是不同的, 不要把 docker.io 之外的站点配置给 registry-mirrors\n\n| 源站               | 替换为                | 备注                                           |\n| ------------------ | --------------------- | ---------------------------------------------- |\n| docker.elastic.co  | elastic.m.daocloud.io |                                                |\n| docker.io          | docker.m.daocloud.io  |                                                |\n| dhi.io             | dhi.m.daocloud.io     |                                                |\n| gcr.io             | gcr.m.daocloud.io     |                                                |\n| ghcr.io            | ghcr.m.daocloud.io    |                                                |\n| k8s.gcr.io         | k8s-gcr.m.daocloud.io | k8s.gcr.io 已被迁移到 registry.k8s.io          |\n| registry.k8s.io    | k8s.m.daocloud.io     |                                                |\n| mcr.microsoft.com  | mcr.m.daocloud.io     |                                                |\n| nvcr.io            | nvcr.m.daocloud.io    |                                                |\n| quay.io            | quay.m.daocloud.io    |                                                |\n| registry.ollama.ai | ollama.m.daocloud.io  | 实验内测中，[使用方法](#加速-ollama--deepseek) |\n\n## 最佳实践\n\n### 部署内网缓存\n\n本地缓存部署用于在内网环境中加速镜像拉取，减少对外网的依赖。通过设置一个本地镜像仓库，您可以缓存常用的镜像。\n[请参考文档](https://github.com/DaoCloud/public-image-mirror/tree/main/docs/local-cache)\n\n### 加速 Kubneretes\n\n#### 加速安装 kubeadm\n\n``` yaml\napiVersion: kubeadm.k8s.io/v1beta3\nkind: ClusterConfiguration\ndns:\n  imageRepository: k8s.m.daocloud.io/coredns\nimageRepository: k8s.m.daocloud.io\n...\n```\n\n#### 加速安装 kind\n\n``` bash\nkind create cluster --name kind --image m.daocloud.io/docker.io/kindest/node:v1.22.1\n```\n\n#### 加速所有 Pod\n\nhttps://github.com/wzshiming/repimage\n\n不修改 yaml, helm 等, 仅使用 Webhook, 自动修改所有新建 Pod 的 image 使用本 mirror\n\n``` bash\nkubectl create -f https://files.m.daocloud.io/github.com/wzshiming/repimage/releases/download/latest/repimage.yaml\nkubectl rollout status deployment/repimage -n kube-system\n```\n\n#### 加速 Containerd\n\n* 参考 Containerd 官方文档: [hosts.md](https://github.com/containerd/containerd/blob/main/docs/hosts.md#registry-host-namespace)\n* 如果您使用 kubespray 安装 containerd, 可以配置 [`containerd_registries_mirrors`](https://github.com/kubernetes-sigs/kubespray/blob/master/docs/CRI/containerd.md#containerd-config)\n\n### 加速 Docker\n\n添加到 `/etc/docker/daemon.json`\n``` json\n{\n  \"registry-mirrors\": [\n    \"https://docker.m.daocloud.io\"\n  ]\n}\n```\n\n### 加速 Ollama & DeepSeek\n\n#### 加速安装 Ollama\n\nCPU:\n```bash\ndocker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama docker.m.daocloud.io/ollama/ollama\n```\n\nGPU 版本:\n1. 首先安装 Nvidia Container Toolkit\n2. 运行以下命令启动 Ollama 容器：\n\n```bash\ndocker run -d --gpus=all -v ollama:/root/.ollama -p 11434:11434 --name ollama docker.m.daocloud.io/ollama/ollama\n```\n\n更多信息请参考：\n* [Ollama Docker 官方文档](https://ollama.com/blog/ollama-is-now-available-as-an-official-docker-image)\n\n#### 加速使用 Deepseek-R1 模型（实验内测中）\n\n如上述步骤，在启动了ollama容器的前提下，还可以通过加速源，加速启动DeepSeek相关的模型服务\n\n注：目前 Ollama 官方源的下载速度已经很快，您也可以直接使用[官方源](https://ollama.com/library/deepseek-r1:1.5b)。\n\n```bash\n# 使用加速源\ndocker exec -it ollama ollama run ollama.m.daocloud.io/library/deepseek-r1:1.5b\n\n# 或直接使用官方源下载模型\n# docker exec -it ollama ollama run deepseek-r1:1.5b\n```\n\n## [友情链接]加速二剑客\n\n* 镜像加速：https://github.com/DaoCloud/public-image-mirror\n* 二进制文件加速：https://github.com/DaoCloud/public-binary-files-mirror\n\n## 贡献者\n\n<a href=\"https://github.com/DaoCloud/public-image-mirror/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=DaoCloud/public-image-mirror\" />\n</a>\n\nMade with [contrib.rocks](https://contrib.rocks).\n"
  },
  {
    "path": "allows.txt",
    "content": "code.forgejo.org/forgejo/forgejo\ncode.forgejo.org/forgejo/runner\ncodeberg.org/forgejo/forgejo\ncontainer-registry.oracle.com/**\ncr.kgateway.dev/kgateway-dev/*\ncr.l5d.io/**\ncr.weaviate.io/**\ndhi.io/**\ndocker.com/kyantech/*\ndocker.elastic.co/**\ndocker.getcollate.io/openmetadata/*\ndocker.io/*\ndocker.io/0nlylty/dockercopilot\ndocker.io/1activegeek/airconnect\ndocker.io/1dev/*\ndocker.io/1panel/maxkb\ndocker.io/4pdosc/k8s-vdevice\ndocker.io/569107519/alertsnitch-mysql\ndocker.io/6053537/portainer-ce\ndocker.io/acim/go-reflex\ndocker.io/acore/*\ndocker.io/acryldata/*\ndocker.io/adguard/adguardhome\ndocker.io/adoptopenjdk/*\ndocker.io/adriansegura99/**\ndocker.io/agentaai/*\ndocker.io/ai/*\ndocker.io/alexxit/go2rtc\ndocker.io/alexzhc/*\ndocker.io/allanpk716/chinesesubfinder\ndocker.io/allfunc/speedtest\ndocker.io/almalinux/*\ndocker.io/alpine/*\ndocker.io/alpinelinux/**\ndocker.io/alseambusher/crontab-ui\ndocker.io/altinity/*\ndocker.io/amambadev/*\ndocker.io/amazon/*\ndocker.io/amd64/*\ndocker.io/amir20/*\ndocker.io/amtoaer/bili-sync-rs\ndocker.io/andrejorsula/space_robotics_bench\ndocker.io/andywuwu/coze2openai\ndocker.io/ankane/pgvector\ndocker.io/apache/*\ndocker.io/apachepulsar/*\ndocker.io/apacherocketmq/*\ndocker.io/apecloud/*\ndocker.io/apereo/cas\ndocker.io/apicurio/*\ndocker.io/apipark/apipark\ndocker.io/apitable/*\ndocker.io/apolloconfig/*\ndocker.io/appbaseio/dejavu\ndocker.io/approachingai/*\ndocker.io/appsmith/appsmith-ce\ndocker.io/appsmith/appsmith-ee\ndocker.io/aquasec/*\ndocker.io/arexadmin01/*\ndocker.io/arey/*\ndocker.io/argoproj/rollouts-demo\ndocker.io/arigaio/*\ndocker.io/arizephoenix/phoenix\ndocker.io/arm64v8/*\ndocker.io/artalk/artalk-go\ndocker.io/ascendai/*\ndocker.io/ascentstream/*\ndocker.io/astral/uv\ndocker.io/atlassian/*\ndocker.io/authelia/authelia\ndocker.io/automatischio/automatisch\ndocker.io/autumn27/scopesentry-scan\ndocker.io/b3log/siyuan\ndocker.io/babashka/babashka\ndocker.io/basecamp/*\ndocker.io/bats/*\ndocker.io/bellsoft/*\ndocker.io/benzino77/clamav-rest-api\ndocker.io/bililive/recorder\ndocker.io/binhex/arch-jellyfin\ndocker.io/binwiederhier/ntfy\ndocker.io/bitnami/*\ndocker.io/bitnamicharts/*\ndocker.io/bitnamilegacy/*\ndocker.io/bluenviron/mediamtx\ndocker.io/boky/postfix\ndocker.io/boredazfcuk/icloudpd\ndocker.io/browserless/*\ndocker.io/browsh/browsh\ndocker.io/budibase/budibase\ndocker.io/budtmo/docker-android\ndocker.io/burakince/mlflow\ndocker.io/bvlc/caffe\ndocker.io/bytebase/bytebase\ndocker.io/bytelang/kplayer\ndocker.io/caarlos0/domain_exporter\ndocker.io/calciumion/new-api\ndocker.io/calico/*\ndocker.io/camunda/zeebe\ndocker.io/canal/canal-server\ndocker.io/caronc/apprise\ndocker.io/cars10/elasticvue\ndocker.io/casbin/casdoor\ndocker.io/certbot/*\ndocker.io/chaosbladeio/chaosblade-box\ndocker.io/chaoszhu/easynode\ndocker.io/charlie0129/bupt-net-login\ndocker.io/chat2db/chat2db\ndocker.io/chatimage/chatchat\ndocker.io/chatwoot/chatwoot\ndocker.io/chengshiwen/influx-proxy\ndocker.io/chengshiwen/influxdb\ndocker.io/chenhw2/aliyun-ddns-cli\ndocker.io/chigusa/bililive-go\ndocker.io/chirpstack/*\ndocker.io/chishin/nginx-proxy-manager-zh\ndocker.io/chrishirsch/kuberhealthy-storage-check\ndocker.io/chrislusf/seaweedfs\ndocker.io/chromedp/headless-shell\ndocker.io/chrstnhntschl/gpu_burn\ndocker.io/cimg/go\ndocker.io/clamav/*\ndocker.io/claraverse/clara-ollama\ndocker.io/clickhouse/*\ndocker.io/clidey/whodb\ndocker.io/cloudflare/*\ndocker.io/cloudnas/clouddrive2-unstable\ndocker.io/cloudnativelabs/kube-router\ndocker.io/cloudreve/cloudreve\ndocker.io/codercom/code-server\ndocker.io/codewisdom/*\ndocker.io/collabora/code\ndocker.io/condaforge/miniforge3\ndocker.io/conduktor/*\ndocker.io/confluentinc/*\ndocker.io/containrrr/watchtower\ndocker.io/continuumio/miniconda3\ndocker.io/coredns/*\ndocker.io/coturn/coturn\ndocker.io/cozedev/*\ndocker.io/cp2k/cp2k\ndocker.io/csiplugin/*\ndocker.io/cturra/ntp\ndocker.io/curlimages/*\ndocker.io/cvat/server\ndocker.io/cvat/ui\ndocker.io/cym1102/nginxwebui\ndocker.io/czerwonk/ping_exporter\ndocker.io/dadoum/anisette-v3-server\ndocker.io/dani-garcia/vaultwarden\ndocker.io/danielqsj/kafka-exporter\ndocker.io/daprio/*\ndocker.io/darthsim/imgproxy\ndocker.io/dataease/sqlbot\ndocker.io/datastax/*\ndocker.io/dbeaver/cloudbeaver\ndocker.io/debezium/*\ndocker.io/deepflowce/*\ndocker.io/deluan/navidrome\ndocker.io/democraticcsi/csi-grpc-proxy\ndocker.io/democraticcsi/democratic-csi\ndocker.io/denoland/deno\ndocker.io/derailed/k9s\ndocker.io/determinedai/*\ndocker.io/devicefarmer/stf\ndocker.io/dezhao/lanraragi_cn\ndocker.io/difegue/lanraragi\ndocker.io/digitalocean/ceph_exporter\ndocker.io/directus/*\ndocker.io/discourse/*\ndocker.io/diygod/*\ndocker.io/docker/*\ndocker.io/dockurr/*\ndocker.io/dokploy/*\ndocker.io/doocs/*\ndocker.io/dorowu/ubuntu-desktop-lxde-vnc\ndocker.io/dpage/*\ndocker.io/dpanel/base-image\ndocker.io/dpanel/dpanel\ndocker.io/dragonflydb/dragonfly\ndocker.io/dragonflyoss/client\ndocker.io/dragonflyoss/dfdaemon\ndocker.io/dragonflyoss/dfinit\ndocker.io/dragonflyoss/manager\ndocker.io/dragonflyoss/scheduler\ndocker.io/dragonflyoss/trainer\ndocker.io/drakkan/sftpgo\ndocker.io/dreamacro/clash\ndocker.io/dremio/dremio-oss\ndocker.io/drone/drone\ndocker.io/drone/drone-runner-docker\ndocker.io/drumsergio/genieacs\ndocker.io/duckdb/duckdb\ndocker.io/dushixiang/kafka-map\ndocker.io/dustynv/*\ndocker.io/dxflrs/*\ndocker.io/e2bdev/code-interpreter\ndocker.io/easytier/easytier\ndocker.io/elastic/*\ndocker.io/electronuserland/builder\ndocker.io/elestio/neko\ndocker.io/eloqdata/*\ndocker.io/elsaworkflows/*\ndocker.io/emberstack/kubernetes-reflector\ndocker.io/emby/*\ndocker.io/emqx/*\ndocker.io/enable/nessus\ndocker.io/ensemblorg/ensembl-vep\ndocker.io/envoyproxy/*\ndocker.io/eolinker/apinto-gateway\ndocker.io/eosphorosai/*\ndocker.io/esphome/*\ndocker.io/estrellaxd/auto_bangumi\ndocker.io/eucm/limesurvey\ndocker.io/exadel/compreface-core\ndocker.io/exceptionless/*\ndocker.io/eyeblue/tank\ndocker.io/f5networks/*\ndocker.io/falcosecurity/*\ndocker.io/falkordb/falkordb\ndocker.io/fatedier/frps\ndocker.io/feiyu563/prometheus-alert\ndocker.io/feiyuyu/filecodebox\ndocker.io/ffdfgdfg/npc\ndocker.io/ffdfgdfg/nps\ndocker.io/fffaraz/fakessh\ndocker.io/filebrowser/filebrowser\ndocker.io/finab/bark-server\ndocker.io/firecow/gitlab-ci-local-util\ndocker.io/fireflyiii/*\ndocker.io/flannel/*\ndocker.io/flannelcni/*\ndocker.io/flashcatcloud/*\ndocker.io/flexget/flexget\ndocker.io/floryn90/hugo\ndocker.io/flowiseai/flowise\ndocker.io/fluent/*\ndocker.io/flyway/flyway\ndocker.io/forceless/pptagent\ndocker.io/fortio/*\ndocker.io/fosrl/*\ndocker.io/foxdalas/*\ndocker.io/frappe/*\ndocker.io/freeradius/freeradius-server\ndocker.io/freesurfer/synthmorph\ndocker.io/frooodle/s-pdf\ndocker.io/frrouting/*\ndocker.io/funcman/115pc\ndocker.io/gaecfovdocker/pulsar-console\ndocker.io/gchq/hdfs\ndocker.io/geoservercloud/*\ndocker.io/germannewsmaker/myspeed\ndocker.io/gerritcodereview/gerrit\ndocker.io/getmeili/*\ndocker.io/getsentry/*\ndocker.io/getwud/wud\ndocker.io/gitea/*\ndocker.io/gitlab/*\ndocker.io/gitpod/openvscode-server\ndocker.io/gliderlabs/logspout\ndocker.io/goacme/lego\ndocker.io/gocd/*\ndocker.io/gogs/gogs\ndocker.io/goharbor/*\ndocker.io/golangci/golangci-lint\ndocker.io/google/*\ndocker.io/goproxy/goproxy\ndocker.io/goreleaser/goreleaser\ndocker.io/gotenberg/gotenberg\ndocker.io/gotify/*\ndocker.io/gotson/komga\ndocker.io/gpustack/gpustack\ndocker.io/gpustack/runner\ndocker.io/grafana/*\ndocker.io/graphiteapp/graphite-statsd\ndocker.io/gravitl/netmaker\ndocker.io/graylog/graylog\ndocker.io/graylog/graylog-datanode\ndocker.io/greatsql/*\ndocker.io/greenbone/*\ndocker.io/greper/certd\ndocker.io/guacamole/*\ndocker.io/guiji2025/*\ndocker.io/gztime/gzctf\ndocker.io/hacdias/webdav\ndocker.io/hagb/docker-easyconnect\ndocker.io/hakuyyf/tensorrtx\ndocker.io/halohub/halo\ndocker.io/hanxi/xiaomusic\ndocker.io/haproxytech/*\ndocker.io/harness/*\ndocker.io/haroldli/xiaoya-tvbox\ndocker.io/hashicorp/*\ndocker.io/headscale/headscale\ndocker.io/heartexlabs/label-studio\ndocker.io/heartexlabs/label-studio-ml-backend\ndocker.io/hectorqin/reader\ndocker.io/hengyunabc/arthas\ndocker.io/henrygd/beszel\ndocker.io/henrygd/beszel-agent\ndocker.io/heroiclabs/nakama-pluginbuilder\ndocker.io/hewenyulucky/*\ndocker.io/hivemq/*\ndocker.io/hiyouga/llamafactory\ndocker.io/hiyouga/pytorch\ndocker.io/hiyouga/verl\ndocker.io/hkalexling/mango\ndocker.io/homeassistant/*\ndocker.io/hoppscotch/hoppscotch\ndocker.io/hpcaitech/colossalai\ndocker.io/hpcaitech/pytorch-cuda\ndocker.io/hslr/sun-panel\ndocker.io/huggingface/*\ndocker.io/hugomods/hugo\ndocker.io/hummingbot/hummingbot\ndocker.io/hybridnetdev/hybridnet\ndocker.io/hyperf/hyperf\ndocker.io/hyperledger/*\ndocker.io/hystax/error_pages_base\ndocker.io/ianw/quickchart\ndocker.io/ibmcom/*\ndocker.io/idootop/mi-gpt\ndocker.io/ihmily/douyin-live-recorder\ndocker.io/imaegoo/twikoo\ndocker.io/infiniflow/*\ndocker.io/infmonkeys/*\ndocker.io/innei/mx-server\ndocker.io/instrumentisto/coturn\ndocker.io/intel/*\ndocker.io/intelanalytics/*\ndocker.io/islandora/code-server\ndocker.io/istio/*\ndocker.io/itzg/minecraft-server\ndocker.io/iyuucn/iyuuplus\ndocker.io/iyuucn/iyuuplus-dev\ndocker.io/jaegertracing/*\ndocker.io/jasonrivers/nagios\ndocker.io/jboss/*\ndocker.io/jc21/nginx-proxy-manager\ndocker.io/jeessy/ddns-go\ndocker.io/jellyfin/*\ndocker.io/jenkins/*\ndocker.io/jenkinsci/*\ndocker.io/jericx/syncclipboard-server\ndocker.io/jetbrains/*\ndocker.io/jettech/*\ndocker.io/jgraph/drawio\ndocker.io/jimmidyson/*\ndocker.io/jitesoft/lighttpd\ndocker.io/jitsi/*\ndocker.io/jlesage/firefox\ndocker.io/jlesage/handbrake\ndocker.io/jmal/jmalcloud\ndocker.io/john119/vlm\ndocker.io/johngong/calibre-web\ndocker.io/joinsunsoft/docker.ui\ndocker.io/joplin/server\ndocker.io/joseluisq/static-web-server\ndocker.io/joxit/docker-registry-ui\ndocker.io/juicedata/*\ndocker.io/jumpserver/*\ndocker.io/jupyter/*\ndocker.io/jupyterhub/*\ndocker.io/justarchi/archisteamfarm\ndocker.io/justlikemaki/openclaw-docker-cn-im\ndocker.io/justsong/one-api\ndocker.io/jvmilazz0/kavita\ndocker.io/jxxghp/*\ndocker.io/k8scloudprovider/*\ndocker.io/kafbat/kafka-ui\ndocker.io/kalilinux/*\ndocker.io/kanidm/*\ndocker.io/karmada/*\ndocker.io/kasmweb/*\ndocker.io/keelhq/keel\ndocker.io/keking/kkfileview\ndocker.io/kennethreitz/*\ndocker.io/kestra/kestra\ndocker.io/keycloak/keycloak\ndocker.io/kicbase/*\ndocker.io/kindest/*\ndocker.io/kiwigrid/*\ndocker.io/klakegg/hugo\ndocker.io/klausmeyer/docker-registry-browser\ndocker.io/koalaman/shellcheck\ndocker.io/koenkk/zigbee2mqtt\ndocker.io/koide3/direct_visual_lidar_calibration\ndocker.io/koishijs/koishi\ndocker.io/kong/*\ndocker.io/kserve/*\ndocker.io/kspacekelvin/fire-python\ndocker.io/kubeedge/*\ndocker.io/kubeflow/*\ndocker.io/kubeflowkatib/*\ndocker.io/kubeflownotebookswg/*\ndocker.io/kubeovn/kube-ovn\ndocker.io/kuberhealthy/*\ndocker.io/kubernetesui/*\ndocker.io/kubeshark/*\ndocker.io/kubeskoop/*\ndocker.io/kubesphere/*\ndocker.io/kubespheredev/ksv-installer\ndocker.io/kusionstack/*\ndocker.io/labring/kubernetes\ndocker.io/langchain/langgraph-api\ndocker.io/langflowai/langflow\ndocker.io/langflowai/langflow-frontend\ndocker.io/langfuse/*\ndocker.io/langgenius/*\ndocker.io/langhuihui/monibuca\ndocker.io/laradock/*\ndocker.io/letta/letta\ndocker.io/lfedge/ekuiper\ndocker.io/lfnovo/open_notebook\ndocker.io/liangjw/kube-webhook-certgen\ndocker.io/library/adminer\ndocker.io/library/aerospike\ndocker.io/library/almalinux\ndocker.io/library/alpine\ndocker.io/library/alt\ndocker.io/library/amazoncorretto\ndocker.io/library/amazonlinux\ndocker.io/library/api-firewall\ndocker.io/library/arangodb\ndocker.io/library/archlinux\ndocker.io/library/backdrop\ndocker.io/library/bash\ndocker.io/library/bonita\ndocker.io/library/buildpack-deps\ndocker.io/library/busybox\ndocker.io/library/caddy\ndocker.io/library/cassandra\ndocker.io/library/centos\ndocker.io/library/chronograf\ndocker.io/library/cirros\ndocker.io/library/clearlinux\ndocker.io/library/clefos\ndocker.io/library/clickhouse\ndocker.io/library/clojure\ndocker.io/library/composer\ndocker.io/library/consul\ndocker.io/library/convertigo\ndocker.io/library/couchbase\ndocker.io/library/couchdb\ndocker.io/library/crate\ndocker.io/library/dart\ndocker.io/library/debian\ndocker.io/library/docker\ndocker.io/library/drupal\ndocker.io/library/eclipse-mosquitto\ndocker.io/library/eclipse-temurin\ndocker.io/library/eggdrop\ndocker.io/library/elasticsearch\ndocker.io/library/elixir\ndocker.io/library/emqx\ndocker.io/library/erlang\ndocker.io/library/express-gateway\ndocker.io/library/fedora\ndocker.io/library/flink\ndocker.io/library/fluentd\ndocker.io/library/friendica\ndocker.io/library/gazebo\ndocker.io/library/gcc\ndocker.io/library/geonetwork\ndocker.io/library/ghost\ndocker.io/library/golang\ndocker.io/library/gradle\ndocker.io/library/groovy\ndocker.io/library/haproxy\ndocker.io/library/haskell\ndocker.io/library/haxe\ndocker.io/library/hello-world\ndocker.io/library/hitch\ndocker.io/library/httpd\ndocker.io/library/hylang\ndocker.io/library/ibm-semeru-runtimes\ndocker.io/library/ibmjava\ndocker.io/library/influxdb\ndocker.io/library/irssi\ndocker.io/library/java\ndocker.io/library/jetty\ndocker.io/library/jobber\ndocker.io/library/joomla\ndocker.io/library/jruby\ndocker.io/library/julia\ndocker.io/library/kapacitor\ndocker.io/library/kibana\ndocker.io/library/kong\ndocker.io/library/lightstreamer\ndocker.io/library/liquibase\ndocker.io/library/logstash\ndocker.io/library/mageia\ndocker.io/library/mariadb\ndocker.io/library/matomo\ndocker.io/library/maven\ndocker.io/library/mediawiki\ndocker.io/library/memcached\ndocker.io/library/mongo\ndocker.io/library/mongo-express\ndocker.io/library/monica\ndocker.io/library/mono\ndocker.io/library/mysql\ndocker.io/library/nats\ndocker.io/library/nats-streaming\ndocker.io/library/neo4j\ndocker.io/library/neurodebian\ndocker.io/library/nextcloud\ndocker.io/library/nginx\ndocker.io/library/node\ndocker.io/library/notary\ndocker.io/library/odoo\ndocker.io/library/open-liberty\ndocker.io/library/openjdk\ndocker.io/library/oraclelinux\ndocker.io/library/orientdb\ndocker.io/library/owncloud\ndocker.io/library/percona\ndocker.io/library/perl\ndocker.io/library/photon\ndocker.io/library/php\ndocker.io/library/php-zendserver\ndocker.io/library/phpmyadmin\ndocker.io/library/plone\ndocker.io/library/postfixadmin\ndocker.io/library/postgres\ndocker.io/library/pypy\ndocker.io/library/python\ndocker.io/library/r-base\ndocker.io/library/rabbitmq\ndocker.io/library/rakudo-star\ndocker.io/library/redis\ndocker.io/library/redmine\ndocker.io/library/registry\ndocker.io/library/rethinkdb\ndocker.io/library/rocket.chat\ndocker.io/library/rockylinux\ndocker.io/library/ros\ndocker.io/library/ruby\ndocker.io/library/rust\ndocker.io/library/sapmachine\ndocker.io/library/satosa\ndocker.io/library/sentry\ndocker.io/library/silverpeas\ndocker.io/library/sl\ndocker.io/library/solr\ndocker.io/library/sonarqube\ndocker.io/library/spark\ndocker.io/library/spiped\ndocker.io/library/storm\ndocker.io/library/swift\ndocker.io/library/swipl\ndocker.io/library/teamspeak\ndocker.io/library/telegraf\ndocker.io/library/tomcat\ndocker.io/library/tomee\ndocker.io/library/traefik\ndocker.io/library/ubuntu\ndocker.io/library/unit\ndocker.io/library/varnish\ndocker.io/library/vault\ndocker.io/library/websphere-liberty\ndocker.io/library/wordpress\ndocker.io/library/xwiki\ndocker.io/library/yourls\ndocker.io/library/znc\ndocker.io/library/zookeeper\ndocker.io/libretranslate/libretranslate\ndocker.io/lihualiu/sam-6d\ndocker.io/linkease/ddnsto\ndocker.io/linkease/desktop-ubuntu-standard-amd64\ndocker.io/linkease/desktop-ubuntu-standard-arm64\ndocker.io/linkease/desktop-ubuntu2-standard-amd64\ndocker.io/linkease/desktop-ubuntu2-standard-arm64\ndocker.io/linkease/drawio-image-export\ndocker.io/linkease/drawio-plantuml-server\ndocker.io/linkease/istoreduprk35xx\ndocker.io/linkease/istoredupx86_64\ndocker.io/linkease/istorepanel\ndocker.io/linkease/kspeeder\ndocker.io/linkease/linkease\ndocker.io/linkease/open-webui\ndocker.io/linkease/pve\ndocker.io/linkease/runmynas\ndocker.io/linkease/webvirtcloud\ndocker.io/linuxserver/*\ndocker.io/linuxsuren/api-testing\ndocker.io/linuxsuren/atest-ext-store-orm\ndocker.io/livekit/*\ndocker.io/liwei2633/gopeed\ndocker.io/lizheming/waline\ndocker.io/lkw199711/smanga\ndocker.io/lldap/lldap\ndocker.io/lmcache/*\ndocker.io/lmsysorg/*\ndocker.io/lobehub/*\ndocker.io/localai/localai\ndocker.io/localstack/localstack\ndocker.io/loggieio/loggie\ndocker.io/longhornio/*\ndocker.io/louislam/*\ndocker.io/luojiecong/index-tts\ndocker.io/m1k1o/*\ndocker.io/mageai/mageai\ndocker.io/maildev/maildev\ndocker.io/mailserver/*\ndocker.io/manjarolinux/*\ndocker.io/manticoresearch/manticore\ndocker.io/maptiler/*\ndocker.io/martialblog/limesurvey\ndocker.io/mattermost/focalboard\ndocker.io/mattermost/mattermost-team-edition\ndocker.io/mauricenino/dashdot\ndocker.io/maxkeytop/*\ndocker.io/mayswind/ezbookkeeping\ndocker.io/mcp/*\ndocker.io/menci/archlinuxarm\ndocker.io/messense/cargo-zigbuild\ndocker.io/metabase/*\ndocker.io/metacontrollerio/metacontroller\ndocker.io/michaelf34/infinity\ndocker.io/mikefarah/yq\ndocker.io/milvusdb/*\ndocker.io/mindsdb/mindsdb\ndocker.io/mineru/sglang\ndocker.io/minio/*\ndocker.io/mintplexlabs/anythingllm\ndocker.io/mirantis/*\ndocker.io/mitmproxy/mitmproxy\ndocker.io/mlikiowa/napcat-docker\ndocker.io/mlocati/php-extension-installer\ndocker.io/mmcauliffe/montreal-forced-aligner\ndocker.io/moby/*\ndocker.io/mohsinonxrm/*\ndocker.io/mongodb/mongodb-community-server\ndocker.io/moonrailgun/tianji\ndocker.io/mpioperator/mpi-operator\ndocker.io/mplatform/manifest-tool\ndocker.io/mpromonet/webrtc-streamer\ndocker.io/mtphotos/mt-photos\ndocker.io/multiarch/*\ndocker.io/mwader/webdav\ndocker.io/myscale/myscaledb\ndocker.io/mysql/*\ndocker.io/n8nio/*\ndocker.io/nacos/*\ndocker.io/nastools/nas-tools\ndocker.io/natsio/*\ndocker.io/ncbi/pgap\ndocker.io/neilpang/acme.sh\ndocker.io/neosmemo/memos\ndocker.io/netbirdio/*\ndocker.io/netbox-community/netbox\ndocker.io/netdata/netdata\ndocker.io/networkstatic/iperf3\ndocker.io/neuvector/*\ndocker.io/newfuture/ddns\ndocker.io/newsnowlabs/dockside\ndocker.io/nextcloud/all-in-one\ndocker.io/nginx/*\ndocker.io/nginxinc/*\ndocker.io/nickfedor/watchtower\ndocker.io/nicolaka/netshoot\ndocker.io/nobodyiam/apollo-quick-start\ndocker.io/nocobase/nocobase\ndocker.io/nocodb/nocodb\ndocker.io/nodered/node-red\ndocker.io/nriver/trilium-cn\ndocker.io/nsqio/nsq\ndocker.io/nvidia/*\ndocker.io/nyanmisaka/jellyfin\ndocker.io/oamdev/*\ndocker.io/oblakstudio/redisinsight\ndocker.io/obsidiandynamics/kafdrop\ndocker.io/oceanbase/oceanbase-ce\ndocker.io/oceanbase/seekdb\ndocker.io/ogarcia/archlinux\ndocker.io/oguzpastirmaci/gpu-burn\ndocker.io/oliver006/*\ndocker.io/ollama/*\ndocker.io/onlyoffice/*\ndocker.io/openclaw/openclaw\ndocker.io/opencloudeu/opencloud-rolling\ndocker.io/opencoze/*\ndocker.io/openebs/*\ndocker.io/openeuler/*\ndocker.io/openfga/*\ndocker.io/opengeminidb/opengemini-server\ndocker.io/opengrok/docker\ndocker.io/openkruise/*\ndocker.io/openlistteam/openlist\ndocker.io/openmetadata/*\ndocker.io/openmined/syft-backend\ndocker.io/openmmlab/*\ndocker.io/openpolicyagent/gatekeeper\ndocker.io/openpolicyagent/opa\ndocker.io/openresty/openresty\ndocker.io/opensearchproject/*\ndocker.io/opensecurity/mobile-security-framework-mobsf\ndocker.io/openstitching/stitch\ndocker.io/opensuse/*\ndocker.io/openvino/*\ndocker.io/openvpn/openvpn-as\ndocker.io/openwhisk/*\ndocker.io/openzipkin/*\ndocker.io/osixia/*\ndocker.io/osrf/*\ndocker.io/ossrs/srs\ndocker.io/otel/*\ndocker.io/outlinesdev/outlines\ndocker.io/outlinewiki/outline\ndocker.io/oven/bun\ndocker.io/owncloud/server\ndocker.io/p3terx/aria2-pro\ndocker.io/p3terx/ariang\ndocker.io/paddlepaddle/paddle\ndocker.io/paketobuildpacks/*\ndocker.io/pandoc/*\ndocker.io/paradedb/*\ndocker.io/passbolt/passbolt\ndocker.io/penpotapp/*\ndocker.io/pepperlabs/peppermint\ndocker.io/percona/*\ndocker.io/pgautoupgrade/pgautoupgrade\ndocker.io/pgrouting/pgrouting\ndocker.io/pgvector/pgvector\ndocker.io/photoprism/photoprism\ndocker.io/phpmyadmin/*\ndocker.io/phpswoole/swoole\ndocker.io/pierky/bird\ndocker.io/pingcap/*\ndocker.io/plantuml/plantuml-server\ndocker.io/plexinc/pms-docker\ndocker.io/plugins/docker\ndocker.io/podwide/cosyvoice\ndocker.io/pointcloudlibrary/env\ndocker.io/polardbx/polardb-x\ndocker.io/portainer/*\ndocker.io/postgis/postgis\ndocker.io/postgrest/postgrest\ndocker.io/pragkent/alidns-webhook\ndocker.io/privoce/vocechat-server\ndocker.io/prodrigestivill/postgres-backup-local\ndocker.io/projectcontour/contour-authserver\ndocker.io/projecthami/*\ndocker.io/prom/*\ndocker.io/prometheuscommunity/*\ndocker.io/provectuslabs/kafka-ui\ndocker.io/proxysql/proxysql\ndocker.io/pymumu/smartdns\ndocker.io/pytorch/*\ndocker.io/qdrant/*\ndocker.io/qdtoday/qd\ndocker.io/qemux/qemu-docker\ndocker.io/qingpan/rnacos\ndocker.io/qmcgaw/ddns-updater\ndocker.io/questdb/questdb\ndocker.io/quickwit/*\ndocker.io/qwenllm/*\ndocker.io/rabbitmqoperator/cluster-operator\ndocker.io/radondb/*\ndocker.io/ramonvc/freegpt-webui\ndocker.io/rancher/*\ndocker.io/rayproject/*\ndocker.io/rclone/*\ndocker.io/reactivetechio/kubegres\ndocker.io/reallibrephotos/librephotos\ndocker.io/reallibrephotos/librephotos-frontend\ndocker.io/reallibrephotos/librephotos-proxy\ndocker.io/redash/*\ndocker.io/redhat/*\ndocker.io/redis/*\ndocker.io/redislabs/*\ndocker.io/rednotehilab/dots.ocr\ndocker.io/redpandadata/console\ndocker.io/redpandadata/kminion\ndocker.io/redroid/redroid\ndocker.io/reportportal/reportportal\ndocker.io/resmoio/kubernetes-event-exporter\ndocker.io/restatedev/restate\ndocker.io/ribbybibby/ssl-exporter\ndocker.io/riscv64/*\ndocker.io/rockylinux/rockylinux\ndocker.io/rocm/*\ndocker.io/rolebasedgroup/rbgs-controller\ndocker.io/romancin/tinymediamanager\ndocker.io/rommapp/romm\ndocker.io/rook/ceph\ndocker.io/rsyslog/*\ndocker.io/rucio/*\ndocker.io/rustdesk/rustdesk-server\ndocker.io/rustdesk/rustdesk-server-pro\ndocker.io/rustdesk/rustdesk-server-s6\ndocker.io/rustfs/rustfs\ndocker.io/rustlang/rust\ndocker.io/rzuo/pose\ndocker.io/sameersbn/**\ndocker.io/savatar101/omniparse\ndocker.io/schemahero/*\ndocker.io/schnell18/rocketmq-dashboard\ndocker.io/seafileltd/seafile-mc\ndocker.io/searxng/searxng\ndocker.io/seataio/*\ndocker.io/secoresearch/rsync\ndocker.io/selectdb/*\ndocker.io/selenium/*\ndocker.io/semgrep/*\ndocker.io/semitechnologies/*\ndocker.io/senthilrch/*\ndocker.io/serengil/deepface\ndocker.io/serversideup/*\ndocker.io/shieldsio/shields\ndocker.io/shingarey/foundationpose_custom_cuda121\ndocker.io/sickcodes/docker-osx\ndocker.io/silkeh/clang\ndocker.io/simonrupf/chronyd\ndocker.io/sinamics/ztnet\ndocker.io/sissbruecker/linkding\ndocker.io/sj26/mailcatcher\ndocker.io/slimerl/slime\ndocker.io/slskd/slskd\ndocker.io/snipe/snipe-it\ndocker.io/snowdreamtech/frpc\ndocker.io/snowdreamtech/frps\ndocker.io/solace/solace-pubsub-standard\ndocker.io/solidnerd/bookstack\ndocker.io/sonatype/*\ndocker.io/sonicorg/sonic-client-web-base\ndocker.io/sonobuoy/*\ndocker.io/soulter/astrbot\ndocker.io/sourcegraph/*\ndocker.io/squidfunk/*\ndocker.io/starrocks/*\ndocker.io/steamcmd/*\ndocker.io/stilleshan/frpc\ndocker.io/stilleshan/frps\ndocker.io/stirlingtools/stirling-pdf\ndocker.io/stnsmith/fossflow\ndocker.io/streamnative/*\ndocker.io/styletang/rocketmq-console-ng\ndocker.io/subfuzion/netcat\ndocker.io/suisuijiang/fiora\ndocker.io/sulinggg/openwrt\ndocker.io/supabase/*\ndocker.io/superbench/superbench\ndocker.io/supermanito/arcadia\ndocker.io/superng6/aria2\ndocker.io/superng6/qbittorrentee\ndocker.io/svhd/logto\ndocker.io/swaggerapi/*\ndocker.io/syncthing/syncthing\ndocker.io/tabbyml/tabby\ndocker.io/tailscale/*\ndocker.io/taksss/php-epg\ndocker.io/talebook/talebook\ndocker.io/talkincode/toughradius\ndocker.io/tarscloud/framework\ndocker.io/tdengine/*\ndocker.io/techblog/broadlinkmanager\ndocker.io/technitium/dns-server\ndocker.io/temporalio/*\ndocker.io/tensorchord/pgvecto-rs\ndocker.io/tensorflow/*\ndocker.io/tensorfusion/*\ndocker.io/teslamate/*\ndocker.io/testcontainers/*\ndocker.io/texlive/texlive\ndocker.io/thanosio/*\ndocker.io/thingsboard/tb-node\ndocker.io/thingsboard/tb-postgres\ndocker.io/thomassong/gpu-admission\ndocker.io/tiangolo/*\ndocker.io/tianon/postgres-upgrade\ndocker.io/timberio/*\ndocker.io/timescale/timescaledb\ndocker.io/timonwong/prometheus-webhook-dingtalk\ndocker.io/timothyjmiller/cloudflare-ddns\ndocker.io/tinygo/tinygo\ndocker.io/tinymediamanager/tinymediamanager\ndocker.io/tnir/mysqlclient\ndocker.io/tomkellygenetics/universc\ndocker.io/tonistiigi/binfmt\ndocker.io/tonistiigi/xx\ndocker.io/traefik/whoami\ndocker.io/trafficserver/trafficserver\ndocker.io/treeverse/lakefs\ndocker.io/triliumnext/notes\ndocker.io/trinodb/trino\ndocker.io/trustpilot/beat-exporter\ndocker.io/tryretool/backend\ndocker.io/tugraph/*\ndocker.io/tunathu/bandersnatch\ndocker.io/tusproject/tusd\ndocker.io/tutelgroup/*\ndocker.io/twinproduction/gatus\ndocker.io/ubuntu/*\ndocker.io/ultralytics/*\ndocker.io/unclecode/crawl4ai\ndocker.io/unityci/editor\ndocker.io/uozi/nginx-ui\ndocker.io/vaalacat/frp-panel\ndocker.io/valkey/valkey\ndocker.io/vaultwarden/server\ndocker.io/vdsm/virtual-dsm\ndocker.io/velero/*\ndocker.io/verdaccio/*\ndocker.io/verlai/*\ndocker.io/vesoft/*\ndocker.io/victoriametrics/*\ndocker.io/viktorstrate/*\ndocker.io/vllm/*\ndocker.io/volcanosh/*\ndocker.io/vulhub/kkfileview\ndocker.io/wallabag/wallabag\ndocker.io/wandb/*\ndocker.io/weaveworks/*\ndocker.io/webdevops/*\ndocker.io/wechatopenai/*\ndocker.io/wekanteam/wekan\ndocker.io/whyour/qinglong\ndocker.io/willfarrell/autoheal\ndocker.io/wiremock/wiremock\ndocker.io/wiznote/wizserver\ndocker.io/woodpeckerci/*\ndocker.io/wurstmeister/kafka\ndocker.io/wurstmeister/zookeeper\ndocker.io/xhofe/alist\ndocker.io/xhongc/music_tag_web\ndocker.io/xiaojusurvey/xiaoju-survey\ndocker.io/xiaoyaliu/alist\ndocker.io/xixihahaliu01/qanything-linux\ndocker.io/xixihahaliu01/qanything-mac\ndocker.io/xixihahaliu01/qanything-win\ndocker.io/xprobe/xinference\ndocker.io/xukuanhit/air_slam\ndocker.io/xuxueli/xxl-job-admin\ndocker.io/yandex/clickhouse-server\ndocker.io/ydlhero/chatgpt-web-midjourney-proxy\ndocker.io/yedf/dtm\ndocker.io/yidadaa/chatgpt-next-web\ndocker.io/ypptec/nascab\ndocker.io/zabbix/*\ndocker.io/zadam/trilium\ndocker.io/zendesk/maxwell\ndocker.io/zerotier/*\ndocker.io/zhaojun1998/zfile-pro\ndocker.io/zhayujie/chatgpt-on-wechat\ndocker.io/zilliz/*\ndocker.io/zlijingtao/neurobfuscator\ndocker.io/zlmediakit/zlmediakit\ndocker.io/zmisgod/iptvchecker\ndocker.io/zmister/mrdoc\ndocker.io/zulip/docker-zulip\ndocker.osgeo.org/**\ndocker.stirlingpdf.com/stirlingtools/stirling-pdf\ngcr.io/**\nghcr.io/666ghj/bettafish\nghcr.io/9001/copyparty-ac\nghcr.io/aas-ee/open-web-search\nghcr.io/actions/**\nghcr.io/advplyr/audiobookshelf\nghcr.io/ajnart/homarr\nghcr.io/amamba-io/**\nghcr.io/analogj/scrutiny\nghcr.io/anduin2017/how-to-cook\nghcr.io/anomalyco/opencode\nghcr.io/apache/**\nghcr.io/apple/**\nghcr.io/aquasecurity/**\nghcr.io/armbian/**\nghcr.io/astral-sh/**\nghcr.io/authzed/spicedb\nghcr.io/authzed/spicedb-operator\nghcr.io/autowarefoundation/autoware\nghcr.io/baizeai/**\nghcr.io/benc-uk/kubeview\nghcr.io/berriai/litellm\nghcr.io/bigcode-project/evaluation-harness\nghcr.io/bigcode-project/evaluation-harness-multiple\nghcr.io/biliup/caution\nghcr.io/binary-husky/gpt_academic_with_latex\nghcr.io/blakeblackshear/**\nghcr.io/brenner-tobias/cloudflared/*\nghcr.io/canner/*\nghcr.io/chaos-mesh/**\nghcr.io/chaosblade-io/**\nghcr.io/chroma-core/chroma\nghcr.io/cinnamon/kotaemon\nghcr.io/cirruslabs/**\nghcr.io/cloudtty/cloudshell\nghcr.io/coder/**\nghcr.io/codex-team/codex.docs\nghcr.io/containerd/**\nghcr.io/coollabsio/coolify-helper\nghcr.io/coqui-ai/tts\nghcr.io/corentinth/it-tools\nghcr.io/cowboysysop/pytest\nghcr.io/crazy-max/fail2ban\nghcr.io/cross-rs/**\nghcr.io/danny-avila/librechat-dev\nghcr.io/daocloud/**\nghcr.io/dbt-labs/dbt-core\nghcr.io/decohererk/decotv\nghcr.io/deepflowio/rust-build\nghcr.io/dexidp/**\nghcr.io/docling-project/*\nghcr.io/dtzar/**\nghcr.io/easytier/easytier\nghcr.io/elastic/opentelemetry-demo\nghcr.io/elf-io/*\nghcr.io/esphome/esphome\nghcr.io/estrellaxd/auto_bangumi\nghcr.io/eunomia-bpf/libbpf-template\nghcr.io/fatedier/frpc\nghcr.io/fief-dev/fief\nghcr.io/fish2018/pansou-web\nghcr.io/fission/**\nghcr.io/flannel-io/*\nghcr.io/flexget/flexget\nghcr.io/fluent/fluent-operator/*\nghcr.io/freecodecamp/devdocs\nghcr.io/gethomepage/homepage\nghcr.io/getsentry/*\nghcr.io/ggerganov/llama.cpp\nghcr.io/ggml-org/llama.cpp\nghcr.io/gnzsnz/ib-gateway\nghcr.io/go-rod/rod\nghcr.io/goauthentik/**\nghcr.io/gohugoio/hugo\nghcr.io/google/**\nghcr.io/graalvm/*\nghcr.io/grafana-operator/*\nghcr.io/grafana/*\nghcr.io/hassio-addons/**\nghcr.io/headlamp-k8s/headlamp\nghcr.io/helm/**\nghcr.io/hkuds/lightrag\nghcr.io/homarr-labs/homarr\nghcr.io/home-assistant/**\nghcr.io/home-operations/*\nghcr.io/huaweiclouddeveloper/**\nghcr.io/huggingface/*\nghcr.io/hwameistor/**\nghcr.io/imagegenius/immich\nghcr.io/immich-app/**\nghcr.io/imputnet/cobalt\nghcr.io/infrastructure-io/**\nghcr.io/inspektor-gadget/gadget/*\nghcr.io/jd-opensource/**\nghcr.io/jimmidyson/configmap-reload\nghcr.io/joeferner/redis-commander\nghcr.io/joernio/joern\nghcr.io/k3d-io/**\nghcr.io/k3s-io/**\nghcr.io/k8snetworkplumbingwg/**\nghcr.io/karakeep-app/karakeep\nghcr.io/kdoctor-io/**\nghcr.io/kedacore/*\nghcr.io/khoj-ai/**\nghcr.io/klts-io/**\nghcr.io/komari-monitor/komari\nghcr.io/koodo-reader/koodo-reader\nghcr.io/koordinator-sh/**\nghcr.io/ksmartdata/**\nghcr.io/kube-vip/**\nghcr.io/kubean-io/**\nghcr.io/kubeflow/**\nghcr.io/kyverno/**\nghcr.io/labring/calico\nghcr.io/labring/fastgpt\nghcr.io/labring/fastgpt-sandbox\nghcr.io/labring/lvscare\nghcr.io/lemker/unifi-os-server\nghcr.io/librespeed/speedtest\nghcr.io/linuxsuren/api-testing\nghcr.io/linuxsuren/atest-ext-store-orm\nghcr.io/llm-d/**\nghcr.io/logseq/logseq-webapp\nghcr.io/lunatechlab/moontv\nghcr.io/luskits/**\nghcr.io/macbre/nginx-http3\nghcr.io/mastodon/mastodon\nghcr.io/maybe-finance/**\nghcr.io/megacloudcontainer/**\nghcr.io/mellanox/**\nghcr.io/mendableai/firecrawl\nghcr.io/metalbear-co/**\nghcr.io/metatool-ai/metamcp\nghcr.io/metatube-community/metatube-server\nghcr.io/microsoft/**\nghcr.io/mlflow/*\nghcr.io/modelcontextprotocol/inspector\nghcr.io/mosn/**\nghcr.io/mostlygeek/llama-swap\nghcr.io/music-assistant/server\nghcr.io/nicholas-fedor/watchtower\nghcr.io/nvidia/**\nghcr.io/open-telemetry/**\nghcr.io/open-webui/open-webui\nghcr.io/open-webui/pipelines\nghcr.io/opencidn/**\nghcr.io/openclaw/openclaw\nghcr.io/openfaas/**\nghcr.io/openinsight-proj/**\nghcr.io/openlistteam/openlist-git\nghcr.io/ot-container-kit/**\nghcr.io/parkervcp/yolks\nghcr.io/phioranex/openclaw-docker\nghcr.io/plankanban/planka\nghcr.io/project-zot/**\nghcr.io/projectcontour/**\nghcr.io/ptbsare/home-assistant-addons/aarch64-addon-sherpa-onnx-tts-stt\nghcr.io/puppeteer/puppeteer\nghcr.io/rails/**\nghcr.io/rancher/**\nghcr.io/rjmalagon/ollama-linux-amd-apu\nghcr.io/seriousm4x/upsnap\nghcr.io/siderolabs/*\nghcr.io/siemens/**\nghcr.io/sillytavern/sillytavern\nghcr.io/songquanpeng/one-api\nghcr.io/speaches-ai/speaches\nghcr.io/spidernet-io/**\nghcr.io/spiffe/**\nghcr.io/spring-ai-alibaba/lynxe\nghcr.io/sugarforever/peanut-shell\nghcr.io/sumologic/**\nghcr.io/suwayomi/suwayomi-server\nghcr.io/suwayomi/tachidesk\nghcr.io/systemed/tilemaker\nghcr.io/szemeng76/lunatv\nghcr.io/tangly1024/notionnext\nghcr.io/timeplus-io/**\nghcr.io/tiryoh/ros2-desktop-vnc\nghcr.io/toeverything/affine-graphql\nghcr.io/umami-software/umami\nghcr.io/universaloj/**\nghcr.io/vllm-project/guidellm\nghcr.io/wg-easy/wg-easy\nghcr.io/wzshiming/**\nghcr.io/ylianst/meshcentral\nghcr.io/zalando/**\nghcr.io/zammad/zammad\nghcr.io/zitadel/**\nk8s.gcr.io/**\nlscr.io/linuxserver/**\nmcr.microsoft.com/**\nnvcr.io/**\nollama.ai/**\npublic.ecr.aws/amazonlinux/**\npublic.ecr.aws/appmesh/**\npublic.ecr.aws/bitnami/*\npublic.ecr.aws/cloudwatch-agent/**\npublic.ecr.aws/datadog/**\npublic.ecr.aws/docker/**\npublic.ecr.aws/dynatrace/**\npublic.ecr.aws/eks-distro/**\npublic.ecr.aws/karpenter/**\npublic.ecr.aws/lambda/**\npublic.ecr.aws/mackerel/**\npublic.ecr.aws/mountpoint-s3-csi-driver/**\npublic.ecr.aws/nginx/**\npublic.ecr.aws/ubuntu/**\nquay.io/aipipeline/*\nquay.io/argoproj/*\nquay.io/argoprojlabs/*\nquay.io/ascend/*\nquay.io/brancz/*\nquay.io/calico/*\nquay.io/ceph/ceph\nquay.io/ceph/cosi\nquay.io/cephcsi/cephcsi\nquay.io/cilium/*\nquay.io/coreos/*\nquay.io/csiaddons/k8s-sidecar\nquay.io/external_storage/*\nquay.io/frrouting/frr\nquay.io/go-skynet/local-ai\nquay.io/goswagger/*\nquay.io/grafana-operator/*\nquay.io/ibm-spectrum-scale/*\nquay.io/jaegertracing/*\nquay.io/jetstack/*\nquay.io/jetstack/charts/*\nquay.io/jupyter/*\nquay.io/jupyterhub/*\nquay.io/k0sproject/*\nquay.io/k8scsi/*\nquay.io/kata-containers/*\nquay.io/keycloak/keycloak\nquay.io/kiali/*\nquay.io/kiwigrid/*\nquay.io/kuberay/*\nquay.io/kubernetes-ingress-controller/*\nquay.io/kubernetes-sigs/*\nquay.io/kubespray/*\nquay.io/kubevirt/*\nquay.io/libpod/skopeo_cidev\nquay.io/metallb/*\nquay.io/minio/*\nquay.io/mongodb/*\nquay.io/nmstate/*\nquay.io/nuclio/*\nquay.io/operator-framework/*\nquay.io/operatorhubio/minio-operator\nquay.io/opstree/*\nquay.io/podman/stable\nquay.io/prometheus-operator/*\nquay.io/prometheus/*\nquay.io/prometheuscommunity/*\nquay.io/quarkus/*\nquay.io/redhat-developer/*\nquay.io/sameersbn/squid\nquay.io/skopeo/*\nquay.io/spotahome/*\nquay.io/strimzi/*\nquay.io/submariner/*\nquay.io/tigera/*\nregistry.developers.crunchydata.com/crunchydata/pgo-deployer\nregistry.gitlab.com/gitlab-org/**\nregistry.gitlab.com/purelb/purelb/purelb\nregistry.heroiclabs.com/heroiclabs/nakama\nregistry.jujucharms.com/**\nregistry.k8s.io/**\nregistry.opensource.zalan.do/**\nregistry.rocket.chat/**\nrocks.canonical.com/**\nus-central1-docker.pkg.dev/k8s-staging-images/**\nus-central1-docker.pkg.dev/keephq/keep/keep-api\nus-central1-docker.pkg.dev/keephq/keep/keep-ui\nus.gcr.io/k8s-artifacts-prod/**\n"
  },
  {
    "path": "docs/local-cache/README.md",
    "content": "# 部署内网缓存\n\n## 简介\n\n本地缓存部署用于在内网环境中加速镜像拉取，减少对外网的依赖。通过设置一个本地镜像仓库，您可以缓存常用的镜像。\n\n## 部署步骤\n\n1. **准备环境**  \n\n确保已安装 Docker 和 Docker Compose。\n\n2. **配置 Docker Compose 文件**  \n\n创建一个 `docker-compose.yml` 文件：\n\n```yaml\nservices:\n  registry:\n    image: m.daocloud.io/docker.io/library/registry:3\n    restart: unless-stopped\n    ports:\n    - 8888:8888\n    command:\n    - /etc/docker/registry/config.yml\n    volumes:\n    - cache-data:/var/lib/registry\n    configs:\n    - source: registry-config\n      target: /etc/docker/registry/config.yml\nconfigs:\n  registry-config:\n    content: |\n      version: 0.1\n      storage:\n        delete:\n          enabled: true\n        filesystem:\n          rootdirectory: /var/lib/registry\n      http:\n        addr: :8888\n      proxy:\n        remoteurl: https://m.daocloud.io\n        ttl: 2160h\nvolumes:\n  cache-data: {}\n```\n\n4. **启动服务**  \n```bash\ndocker compose up -d\n```\n\n5. **配置 Docker 客户端**  \n在 `/etc/docker/daemon.json` 中添加以下内容：\n```json\n{\n  \"insecure-registries\": [\"<your-registry-ip>:<your-registry-port>\"]\n}\n\n```\n然后重启 Docker 服务：\n```bash\nsystemctl restart docker\n```\n\n## 用法\n\n现在您的 `<your-registry-ip>:<your-registry-port>/` 已经是 `m.daocloud.io/` 的本地缓存代理\n\n后续就像 `m.daocloud.io` 加前缀一样, 只需要在原始镜像地址前加上 `<your-registry-ip>:<your-registry-port>/` 即可。\n\n例如，拉取 `docker.io/library/nginx:latest` 镜像，可以使用以下命令：\n```bash\ndocker pull <your-registry-ip>:<your-registry-port>/docker.io/library/nginx:latest\n```\n\n"
  },
  {
    "path": "hack/badge.sh",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nQUICKLY=\"${QUICKLY:-}\"\ncat *\"_sync.log\" > \"sync.log\"\nsync=\"$(cat \"sync.log\" | grep \" SYNCHRONIZED: \" | wc -l | tr -d ' ' || :)\"\nunsync=\"$(cat \"sync.log\" | grep \" NOT-SYNCHRONIZED: \" | wc -l | tr -d ' ' || :)\"\nsum=$(($sync + $unsync))\n\nif [[ \"${sum}\" -eq 0 ]]; then\n    echo \"No sync\"\n    exit 1    \nfi\n\nif [[ \"${QUICKLY}\" == \"true\" ]]; then\n    echo \"https://img.shields.io/badge/Sync-${sync}%2F${sum}-blue\"\n    wget \"https://img.shields.io/badge/Sync-${sync}%2F${sum}-blue\" -O badge.svg\nelse\n    echo \"https://img.shields.io/badge/Deep%20Sync-${sync}%2F${sum}-blue\"\n    wget \"https://img.shields.io/badge/Deep%20Sync-${sync}%2F${sum}-blue\" -O badge.svg\nfi\n"
  },
  {
    "path": "hack/correct-image.sh",
    "content": "#!/usr/bin/env bash\n\nfunction guess_image() {\n    local image=\"${1}\"\n\n    image=\"${image// /}\"\n    image=\"${image#\\/}\"\n    image=\"${image%\\/}\"\n\n    if [[ -z \"${image}\" ]]; then\n        return\n    fi\n\n    if [[ \"${image}\" == *\"registry.hub.docker.com/r/\"* ]]; then\n        image=\"docker.io/${image##*registry.hub.docker.com\\/r\\/}\"\n    fi\n    if [[ \"${image}\" == *\"hub.docker.com/r/\"* ]]; then\n        image=\"docker.io/${image##*hub.docker.com\\/r\\/}\"\n    fi\n    if [[ \"${image}\" != *\"/\"* ]]; then\n        image=\"library/${image}\"\n    fi\n    if [[ \"${image%%/*}\" != *\".\"* ]]; then\n        image=\"docker.io/${image}\"\n    fi\n    if [[ \"${image}\" != *\":\"* ]]; then\n        image=\"${image}:latest\"\n    fi\n    if [[ \"${image}\" == *\"//\"* ]] || [[ \"${image}\" == *\" \"* ]]; then\n        return\n    fi\n\n    echo \"${image}\"\n}\n\nguess_image \"${1}\"\n"
  },
  {
    "path": "hack/diff-image.sh",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\n# Output more information that is out of synchronize\nDEBUG=\"${DEBUG:-}\"\n\nIMAGE1=\"${1:-}\"\nIMAGE2=\"${2:-}\"\n\nSKOPEO=\"${SKOPEO:-skopeo}\"\nJQ=\"${JQ:-jq}\"\n\n# Allow image2 to have more tags than image1\nINCREMENTAL=\"${INCREMENTAL:-}\"\n\n# Compare only tags that are in both images\nQUICKLY=\"${QUICKLY:-}\"\n\n# If set, will compare the image tag patterns\nQUICKLY_PATTERN=\"${QUICKLY_PATTERN:-}\"\n\n# Regexp that matches the tags\nFOCUS=\"${FOCUS:-}\"\n\n# Regexp that matches the tags that needs to be skipped\nSKIP=\"${SKIP:-}\"\n\n# Compare the number of tags in parallel\nPARALLET=\"${PARALLET:-0}\"\n\n# Synchronize images from source to destination\nSYNC=\"${SYNC:-}\"\n\n# Retry times\nRETRY=\"${RETRY:-5}\"\n\nSELF=\"$(basename \"${BASH_SOURCE[0]}\")\"\n\nif [[ \"${DEBUG}\" == \"true\" ]]; then\n    echo \"DEBUG:           ${DEBUG}\"\n    echo \"IMAGE1:          ${IMAGE1}\"\n    echo \"IMAGE2:          ${IMAGE2}\"\n    echo \"SKOPEO:          ${SKOPEO}\"\n    echo \"JQ:              ${JQ}\"\n    echo \"INCREMENTAL:     ${INCREMENTAL}\"\n    echo \"QUICKLY:         ${QUICKLY}\"\n    echo \"QUICKLY_PATTERN: ${QUICKLY_PATTERN}\"\n    echo \"FOCUS:           ${FOCUS}\"\n    echo \"SKIP:            ${SKIP}\"\n    echo \"PARALLET:        ${PARALLET}\"\n    echo \"SYNC:            ${SYNC}\"\n    echo \"RETRY:           ${RETRY}\"\nfi\n\nfunction check() {\n    local image1=\"${1:-}\"\n    local image2=\"${2:-}\"\n\n    if [[ \"${image1}\" == \"\" ]] || [[ \"${image2}\" == \"\" ]]; then\n        echo \"Compares whether the synchronization of the two images is exactly the same\"\n        echo \"Need to install jq and skopeo\"\n        echo \"Usage:\"\n        echo \" ${SELF}: <image1> <image2>\"\n        echo \" ${SELF}: <image1:tag> <image2:tag>\"\n        echo \"Env:\"\n        echo \" DEBUG=true                # Output more information that is out of synchronize\"\n        echo \" INCREMENTAL=true          # Allow image2 to have more tags than image1\"\n        echo \" QUICKLY=true              # Compare only tags that are in both images\"\n        echo \" QUICKLY_PATTERN=<pattern> # Regexp that matches the tags\"\n        echo \" FOCUS=<pattern>           # Regexp that matches the tags\"\n        echo \" SKIP=<pattern>            # Regexp that matches the tags that needs to be skipped\"\n        echo \" PARALLET=<size>           # Compare the number of tags in parallel\"\n        echo \" SYNC=true                 # Synchronize images from source to destination\"\n        echo \" RETRY=<times>             # Retry times\"\n        return 2\n    fi\n\n    if [[ \"${image1#*/}\" =~ \":\" ]]; then\n        if [[ \"${image2#*/}\" =~ \":\" ]]; then\n            return 0\n        else\n            echo \"${SELF}: ERROR: ${image1} and ${image2} must both be full images or not be tag references\" >&2\n            return 2\n        fi\n    else\n        if [[ \"${image2#*/}\" =~ \":\" ]]; then\n            echo \"${SELF}: ERROR: ${image1} and ${image2} must both be full images or not be tag references\" >&2\n            return 2\n        else\n            return 0\n        fi\n    fi\n}\n\nemptyLayer=\"sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4\"\n\nfunction inspect() {\n    local image=\"${1:-}\"\n    local raw=$(${SKOPEO} inspect --retry-times \"${RETRY}\" --raw --tls-verify=false \"docker://${image}\")\n    if [[ \"${raw}\" == \"\" ]]; then\n        echo \"skopeo inspect --retry-times \"${RETRY}\" --raw --tls-verify=false docker://${image}\" >&2\n        echo \"ERROR: Failed to inspect ${image}\" >&2\n        return 1\n    fi\n\n    local schemaVersion=$(echo \"${raw}\" | ${JQ} -r '.schemaVersion')\n    case \"${schemaVersion}\" in\n    1)\n        echo \"${raw}\" | ${JQ} -r '.fsLayers[].blobSum' | grep -v \"${emptyLayer}\" | tac\n        ;;\n    2)\n        local mediaType=$(echo \"${raw}\" | ${JQ} -r '.mediaType // \"\" ')\n        if [[ \"${mediaType}\" == \"\" ]]; then\n            if [[ \"$(echo \"${raw}\" | ${JQ} -r '.layers | length')\" -gt 0 ]]; then\n                mediaType=\"layers\"\n            elif [[ \"$(echo \"${raw}\" | ${JQ} -r '.manifests | length')\" -gt 0 ]]; then\n                mediaType=\"manifests\"\n            fi\n        fi\n\n        case \"${mediaType}\" in\n        \"layers\" | \"application/vnd.docker.distribution.manifest.v2+json\")\n            echo \"${raw}\" | ${JQ} -r '.layers[].digest' | grep -v \"${emptyLayer}\"\n            ;;\n        \"manifests\" | \"application/vnd.docker.distribution.manifest.list.v2+json\")\n            local line=$(echo \"${raw}\" | ${JQ} -j '.manifests[] | .platform.architecture , \" \" , .platform.os , \"\\n\"' | sort)\n            IFS=$'\\n'\n            for args in ${line}; do\n                local arch=\"${args%% *}\"\n                local os=\"${args##* }\"\n                echo ${args}\n                ${SKOPEO} --override-arch \"${arch}\" --override-os \"${os}\" inspect --retry-times \"${RETRY}\" --config --tls-verify=false \"docker://${image}\" | jq -r '.rootfs.diff_ids[]'\n            done\n            unset IFS\n            ;;\n        *)\n            echo \"skopeo inspect --retry-times \"${RETRY}\" --raw --tls-verify=false docker://${image}\" >&2\n            if [[ \"${DEBUG}\" == \"true\" ]]; then\n                echo \"${raw}\" >&2\n            fi\n            echo \"${SELF}: ERROR: Unknown media type: ${mediaType}\" >&2\n            return 2\n            ;;\n        esac\n        ;;\n    *)\n        echo \"skopeo inspect --retry-times \"${RETRY}\" --raw --tls-verify=false docker://${image}\" >&2\n        if [[ \"${DEBUG}\" == \"true\" ]]; then\n            echo \"${raw}\" >&2\n        fi\n        echo \"${SELF}: ERROR: Unknown schema version: ${schemaVersion}\" >&2\n        return 2\n        ;;\n    esac\n}\n\nfunction copy-image() {\n    local image1=\"${1:-}\"\n    local image2=\"${2:-}\"\n\n    ${SKOPEO} copy --retry-times \"${RETRY}\" --all --dest-tls-verify=false \"docker://${image1}\" \"docker://${image2}\"\n}\n\nfunction list-tags() {\n    local image=\"${1:-}\"\n    local raw=\"$(${SKOPEO} list-tags --retry-times \"${RETRY}\" --tls-verify=false \"docker://${image}\" | ${JQ} -r '.Tags[]')\"\n\n    # Sort by string length\n    raw=$(echo \"${raw}\" | awk '{print length, $0}' | sort -n | awk '{print $2}')\n\n    if [[ \"${FOCUS}\" != \"\" ]]; then\n        local skip=$(echo \"${raw}\" | grep -v -E \"${FOCUS}\")\n        if [[ \"${skip}\" != \"\" ]]; then\n            echo \"${SELF}: SKIP: ${image} with focus: ${FOCUS}:\" ${skip} >&2\n        fi\n        raw=\"$(echo \"${raw}\" | grep -E \"${FOCUS}\" || :)\"\n    fi\n\n    if [[ \"${SKIP}\" != \"\" ]]; then\n        local skip=$(echo \"${raw}\" | grep -E \"${SKIP}\")\n        if [[ \"${skip}\" != \"\" ]]; then\n            echo \"${SELF}: SKIP: ${image} with skip: ${SKIP}:\" ${skip} >&2\n        fi\n        raw=\"$(echo \"${raw}\" | grep -v -E \"${SKIP}\" || :)\"\n    fi\n    echo \"${raw}\"\n}\n\nfunction diff-image-with-tag() {\n    local image1=\"${1:-}\"\n    local image2=\"${2:-}\"\n\n    if [[ \"${QUICKLY}\" == \"true\" ]]; then\n        local tag1=\"${image1##*:}\"\n        local tag2=\"${image2##*:}\"\n        if [[ \"${tag1}\" != \"${tag2}\" ]]; then\n            echo \"${SELF}: NOT-SYNCHRONIZED: ${image1} and ${image2} are not in synchronized\" >&2\n            return 1\n        fi\n         \n        if [[ \"${QUICKLY_PATTERN}\" == \"\" || (\"${QUICKLY_PATTERN}\" != \"\" && \"${tag1}\" =~ ${QUICKLY_PATTERN}) ]]; then\n            echo \"${SELF}: SYNCHRONIZED: ${image1} and ${image2} are in synchronized\" >&2\n            return 0\n        fi\n    fi\n\n    local inspect2=\"$(inspect ${image2})\"\n    if [[ \"${inspect2}\" == \"\" ]]; then\n        echo \"${SELF}: NOT-SYNCHRONIZED: ${image1} and ${image2} are not in synchronized, ${image2} content is empty\" >&2\n        return 1\n    fi\n\n    local inspect1=\"$(inspect ${image1})\"\n    local diff_raw=$(diff --unified <(echo \"${inspect1}\") <(echo \"${inspect2}\"))\n\n    if [[ \"${diff_raw}\" != \"\" ]]; then\n        echo \"${SELF}: NOT-SYNCHRONIZED: ${image1} and ${image2} are not in synchronized\" >&2\n        if [[ \"${DEBUG}\" == \"true\" ]]; then\n            echo \"DEBUG: image1 ${image1}:\" >&2\n            echo \"${inspect1}\" >&2\n            echo \"DEBUG: image2 ${image2}:\" >&2\n            echo \"${inspect2}\" >&2\n            echo \"diff:\" >&2\n            echo \"${diff_raw}\" >&2\n        fi\n        return 1\n    fi\n    echo \"${SELF}: SYNCHRONIZED: ${image1} and ${image2} are in synchronized\" >&2\n}\n\nfunction diff-image() {\n    local image1=\"${1:-}\"\n    local image2=\"${2:-}\"\n\n    local tags1=\"$(list-tags ${image1})\"\n    local tags2=\"$(list-tags ${image2})\"\n    local diff_raw=\"$(diff --unified <(echo \"${tags1}\") <(echo \"${tags2}\") | grep -v -E '^---' | grep -v -E '^\\+\\+\\+' || :)\"\n    local increase=\"$(echo \"${diff_raw}\" | grep -E '^\\+' | sed 's/^\\+//' || :)\"\n    local reduce=\"$(echo \"${diff_raw}\" | grep -E '^-' | sed 's/^-//' || :)\"\n    local common=\"${tags1}\"\n\n    if [[ \"${increase}\" != \"\" ]]; then\n        common=\"$(echo \"${common}\" | grep -v -f <(echo \"${increase}\") || :)\"\n    fi\n\n    if [[ \"${reduce}\" != \"\" ]]; then\n        common=\"$(echo \"${common}\" | grep -v -f <(echo \"${reduce}\") || :)\"\n    fi\n\n    if [[ \"${INCREMENTAL}\" == \"true\" ]]; then\n        increase=\"\"\n    fi\n\n    if [[ \"${QUICKLY}\" == \"\" ]] || [[ \"${reduce}\" != \"\" ]] || [[ \"${increase}\" != \"\" ]]; then\n        echo \"${SELF}: NOT-SYNCHRONIZED-TAGS: ${image1} and ${image2} are not in synchronized\" >&2\n        if [[ \"${DEBUG}\" == \"true\" ]]; then\n            echo \"DEBUG: image1 ${image1}:\" >&2\n            echo \"${tags1}\" >&2\n            echo \"DEBUG: image2 ${image2}:\" >&2\n            echo \"${tags2}\" >&2\n            echo \"DEBUG: diff:\" >&2\n            echo \"${diff_raw}\" >&2\n        fi\n        for tag in ${reduce}; do\n            echo \"${SELF}: NOT-SYNCHRONIZED: ${image1}:${tag} and ${image2}:${tag} are not in synchronized, ${image2}:${tag} does not exist\" >&2\n            if [[ \"${SYNC}\" == \"true\" ]]; then\n                echo \"${SELF}: SYNCHRONIZE: synchronize from ${image1}:${tag} to ${image2}:${tag}\" >&2\n                copy-image \"${image1}:${tag}\" \"${image2}:${tag}\" >&2\n            fi\n        done\n        for tag in ${increase}; do\n            echo \"${SELF}: NOT-SYNCHRONIZED: ${image1}:${tag} and ${image2}:${tag} are not in synchronized, ${image1}:${tag} does not exist\" >&2\n        done\n        echo \"${common}\"\n        return 1\n    fi\n    echo \"${SELF}: SYNCHRONIZED-TAGS: ${image1} and ${image2} are in synchronized\" >&2\n    echo \"${common}\"\n    return 0\n}\n\nfunction wait_jobs() {\n    local job_num=${1:-3}\n    local perc=$(jobs -p | wc -l)\n    while [ \"${perc}\" -gt \"${job_num}\" ]; do\n        sleep 1\n        perc=$(jobs -p | wc -l)\n    done\n}\n\nfunction main() {\n    local image1=\"${1:-}\"\n    local image2=\"${2:-}\"\n\n    if [[ \"${image1#*/}\" =~ \":\" ]]; then\n        if [[ \"${SYNC}\" == \"true\" ]]; then\n            echo \"${SELF}: SYNCHRONIZE: synchronize from ${image1} to ${image2}\" >&2\n            copy-image \"${image1}\" \"${image2}\"\n            return $?\n        fi\n        diff-image-with-tag \"${image1}\" \"${image2}\" >/dev/null\n        return $?\n    fi\n\n    local list=$(diff-image \"${image1}\" \"${image2}\")\n\n    local notsynced=()\n    if [[ \"${PARALLET}\" -eq 0 ]]; then\n        for tag in ${list}; do\n            diff-image-with-tag \"${image1}:${tag}\" \"${image2}:${tag}\" >/dev/null || {\n                if [[ \"${SYNC}\" == \"true\" ]]; then\n                    echo \"${SELF}: SYNCHRONIZE: synchronize from ${image1}:${tag} to ${image2}:${tag}\" >&2\n                    copy-image \"${image1}:${tag}\" \"${image2}:${tag}\"\n                fi\n                notsynced+=(\"${tag}\")\n            }\n        done\n    else\n        for tag in ${list}; do\n            wait_jobs \"${PARALLET}\"\n            diff-image-with-tag \"${image1}:${tag}\" \"${image2}:${tag}\" >/dev/null || {\n                if [[ \"${SYNC}\" == \"true\" ]]; then\n                    echo \"${SELF}: SYNCHRONIZE: synchronize from ${image1}:${tag} to ${image2}:${tag}\" >&2\n                    copy-image \"${image1}:${tag}\" \"${image2}:${tag}\"\n                fi\n                notsynced+=(\"${tag}\")\n            } &\n        done\n        wait\n    fi\n\n    if [[ \"${#notsynced[@]}\" -gt 0 ]]; then\n        echo \"${SELF}: INFO: ${image1} and ${image2} are not in synchronized, there are not synchronized tags ${#notsynced[@]}: ${notsynced[*]}\" >&2\n        return 1\n    fi\n}\n\ncheck \"${IMAGE1}\" \"${IMAGE2}\"\nmain \"${IMAGE1}\" \"${IMAGE2}\"\n"
  },
  {
    "path": "hack/diff.sh",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nsource \"$(dirname \"${BASH_SOURCE}\")/helper.sh\"\ncd \"${ROOT}\"\n\nDEBUG=\"${DEBUG:-}\"\nINCREMENTAL=\"${INCREMENTAL:-}\"\nQUICKLY=\"${QUICKLY:-}\"\nSYNC=\"${SYNC:-}\"\nPARALLET=\"${PARALLET:-0}\"\nPARALLET_JOBS=\"${PARALLET_JOBS:-4}\"\nEXCLUDE=\"$(helper::exclude)\"\n\ndeclare -A DOMAIN_MAP=()\n\nfunction wait_jobs() {\n    local job_num=${1:-3}\n    local perc=$(jobs -p | wc -l)\n    while [ \"${perc}\" -gt \"${job_num}\" ]; do\n        sleep 1\n        perc=$(jobs -p | wc -l)\n    done\n}\n\nfunction sync_with_domain() {\n    local domain=\"${1}\"\n\n    local list=$(echo ${DOMAIN_MAP[${domain}]} | tr ' ' '\\n' | shuf)\n    for image in ${list}; do\n        regex=\"${DEFAULT_REGEX}\"\n        if [[ \"${image#*/}\" =~ \":\" ]]; then\n            regex=\"${image##*:}\"\n            image=\"${image%:*}\"\n        fi\n        local to=\"$(helper::replace_domain \"${domain}/${image}\")\"\n\n        local logfile=\"${to//\\//_}_sync.log\"\n        echo >\"${logfile}\"\n\n        DEBUG=\"${DEBUG}\" SYNC=\"${SYNC}\" QUICKLY=\"${QUICKLY}\" INCREMENTAL=\"${INCREMENTAL}\" PARALLET=\"${PARALLET}\" FOCUS=\"${regex}\" SKIP=\"${EXCLUDE}\" ./hack/diff-image.sh \"${domain}/${image}\" \"${to}\" 2>&1 | tee -a \"${logfile}\" || {\n            echo \"Error: diff image ${domain}/${image} $(helper::replace_domain \"${domain}/${image}\")\"\n        }\n    done\n}\n\nfunction main() {\n\n    for image in $(helper::get_source); do\n        key=\"${image%%/*}\"\n        val=\"${image#*/}\"\n        if [[ -v \"DOMAIN_MAP[${key}]\" ]]; then\n            DOMAIN_MAP[\"${key}\"]+=\" ${val}\"\n        else\n            DOMAIN_MAP[\"${key}\"]=\"${val}\"\n        fi\n    done\n\n    for domain in \"${!DOMAIN_MAP[@]}\"; do\n        if [[ \"${PARALLET_JOBS}\" -eq 0 ]]; then\n            sync_with_domain \"${domain}\"\n        else\n            wait_jobs \"${PARALLET_JOBS}\"\n            sync_with_domain \"${domain}\" &\n        fi\n    done\n\n    wait\n}\n\ntrap \"trap - SIGTERM && kill 0 && echo exit...\" SIGTERM SIGINT\n\nmain\n"
  },
  {
    "path": "hack/fmt-image-match.sh",
    "content": "#!/usr/bin/env bash\n\nfunction check_match() {\n    local image=$1\n    local lines=$2\n    for line in ${lines}; do\n        if [[ \"${line}\" == *\"/**\" ]]; then\n            if [[ \"${image}\" == \"${line%\\*\\*}\"* ]]; then\n                return\n            fi\n        elif [[ \"${line}\" == *\"/*\" ]]; then\n            if [[ \"${image}\" == \"${line%\\*}\"* ]]; then\n                if [[ \"${image#\"${line%\\*}\"}\" != *\"/\"* ]]; then\n                    return\n                fi\n            fi\n        fi\n    done\n\n    echo \"${image}\"\n}\n\nfunction check_match_more() {\n    local image=$1\n    local lines=$2\n    for line in ${lines}; do\n        if [[ \"${line}\" == *\"/**\" ]]; then\n            if [[ \"${image}\" == \"${line%\\*\\*}\"* ]]; then\n                return\n            fi\n        fi\n    done\n\n    echo \"${image}\"\n}\n\nfunction format() {\n    local file=$1\n    local lines=\"$(cat \"${file}\")\"\n    for line in ${lines}; do\n        if [[ \"${line}\" != *\"*\" ]]; then\n            check_match  \"${line}\" \"${lines}\"\n        fi\n    done\n\n    for line in ${lines}; do\n        if [[ \"${line}\" == *\"/**\" ]]; then\n            echo \"${line}\"\n        elif [[ \"${line}\" == *\"/*\" ]]; then\n            check_match_more  \"${line}\" \"${lines}\"\n        fi\n    done\n}\n\nexport LC_ALL=C\nfile=$1\n\nformat \"${file}\" |\n    sort -u |\n    grep -v '^$' >$1.tmp && mv $1.tmp $1\n"
  },
  {
    "path": "hack/fmt-image.sh",
    "content": "#!/usr/bin/env bash\n\nfunction filter_docker_library() {\n    while read -r line; do\n        if [[ $line =~ ^docker\\.io/[^/]*$ ]]; then\n            echo \"docker.io/library/${line#docker.io/}\"\n        else\n            echo \"${line}\"\n        fi\n    done\n}\n\nfunction filter_k8s_old() {\n    while read -r line; do\n        if [[ $line =~ ^k8s\\.gcr\\.io/.*$ ]]; then\n            echo \"registry.k8s.io/${line#k8s.gcr.io/}\"\n        else\n            echo \"${line}\"\n        fi\n    done\n}\n\ncat $1 |\n    filter_docker_library |\n    filter_k8s_old >$1.tmp && mv $1.tmp $1\n"
  },
  {
    "path": "hack/fmt.sh",
    "content": "#!/usr/bin/env bash\n\nexport LC_ALL=C\n\ncat $1 |\n    sort -u |\n    grep -v '^$' >$1.tmp && mv $1.tmp $1\n"
  },
  {
    "path": "hack/helper.sh",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nROOT=\"${ROOT:-$(dirname \"${BASH_SOURCE}\")/..}\"\nDEFAULT_REGEX='^([a-z]+-)?[a-z]*[0-9]+(\\.[0-9]+){1,2}'\nSKOPEO=\"${SKOPEO:-skopeo}\"\nROOT=$(realpath ${ROOT})\nDOMAIN=\"${DOMAIN:-m.daocloud.io}\"\n\nfunction helper::replace_domain() {\n    local domain=\"${1}\"\n    echo \"${DOMAIN}/${domain}\"\n}\n\nfunction helper::get_source() {\n    local source=\"${1:-mirror.txt}\"\n    cat \"${source}\" | tr -d ' ' | grep -v -E '^$' | grep -v -E '^#'\n}\n\nfunction helper::exclude() {\n    local exclude=\"${1:-exclude.txt}\"\n    local tmp=$(cat \"${exclude}\" | tr -d ' ' | grep -v -E '^$' | grep -v -E '^#' | tr '\\n' '|')\n    echo \"${tmp%|}\"\n}\n"
  },
  {
    "path": "hack/merge-mirror.sh",
    "content": "#!/usr/bin/env bash\n\nbase_list=\"${1}\"\nused_list=\"${2}\"\nused_top=\"${3:-100}\"\n\nfunction used_top() {\n    cat \"${used_list}\" | head -n \"${used_top}\"\n}\n\nfunction intersection_used() {\n    sort \"${base_list}\" \"${used_list}\" | uniq -d\n}\n\nfunction fixed_docker() {\n    grep \"^docker\\.io/library/\" \"${base_list}\"\n    grep \"^docker\\.io/library/\" \"${used_list}\"\n}\n\nfunction fixed_k8s() {\n    grep \"^registry\\.k8s\\.io/\" \"${base_list}\"\n    grep \"^registry\\.k8s\\.io/\" \"${used_list}\"\n}\n\nfunction fixed_istio() {\n    grep \"^docker\\.io/istio/\" \"${base_list}\"\n    grep \"^docker\\.io/istio/\" \"${used_list}\"\n}\n\ncat <(used_top) \\\n    <(intersection_used) \\\n    <(fixed_docker) \\\n    <(fixed_k8s) | sort | uniq -u\n"
  },
  {
    "path": "hack/stats-not-sync.sh",
    "content": "#!/usr/bin/env bash\n\ncat $1  | grep NOT-SYNCHRONIZED | awk '{print $3}' | grep ':' | tr ':' ' ' | awk '{print $1}' | uniq -c | sort -nrk 1\n"
  },
  {
    "path": "hack/verify-allows.sh",
    "content": "#!/usr/bin/env bash\n\nfile=$1\n\nimage=$2\n\nfunction check_allows() {\n    local file=$1\n    local image=$2\n    if [[ \"${image}\" == *\":\" ]]; then\n        return 1\n    fi\n    while read line; do\n        if [[ \"${line}\" == *\"**\" ]]; then\n            if [[ \"${image}\" == \"${line%\\*\\*}\"* ]]; then\n                return 0\n            fi\n        elif [[ \"${line}\" == *\"*\" ]]; then\n            if [[ \"${image}\" == \"${line%\\*}\"* ]]; then\n                if [[ \"${image#\"${line%\\*}\"}\" != *\"/\"* ]]; then\n                    return 0\n                fi\n            fi\n        elif [[ \"${line}\" == \"${image%\\:*}\" ]]; then\n            return 0\n        fi\n    done <\"${file}\"\n\n    return 1\n}\n\ncheck_allows \"${file}\" \"${image}\"\n"
  },
  {
    "path": "hack/verify-docker-prefix.sh",
    "content": "#!/usr/bin/env bash\n\nfile=$1\n\ncp ${file} ${file}.bak\n\ncat ${file} | grep docker.io | grep library | sed 's#docker.io/library/#docker.io/#' >>${file}.bak\n\ncat ${file} | grep -e \"docker\\.io/\\w\\+:\\|docker\\.io/\\w\\+$\" | sed 's#docker.io/#docker.io/library/#' >>${file}.bak\n\n$(dirname \"${BASH_SOURCE}\")/fmt.sh ${file}.bak\n\nresult=$(diff ${file} ${file}.bak)\n\nif [[ \"${result}\" != \"\" ]]; then\n    echo \"Usually docker.io/* and docker.io/library/* appear in pairs \"\n    echo \"Please run following command to fix the issue:\"\n    echo \"cat <<EOF >> ${file}\"\n    echo \"${result}\" | grep \"^>\" | sed 's/^>\\s\\+//'\n    echo \"EOF\"\n    echo \"./hack/fmt.sh ${file}\"\n\n    exit 1\nfi\n\nrm ${file}.bak\n"
  },
  {
    "path": "hack/verify-fmt-image.sh",
    "content": "#!/usr/bin/env bash\n\nexport LC_ALL=C\n\ncp $1 $1.bak\n\n$(dirname \"${BASH_SOURCE}\")/fmt-image.sh $1.bak\n\ndiff -c $1 $1.bak && rm $1.bak\n"
  },
  {
    "path": "hack/verify-fmt.sh",
    "content": "#!/usr/bin/env bash\n\nexport LC_ALL=C\n\ncp $1 $1.bak\n\n$(dirname \"${BASH_SOURCE}\")/fmt.sh $1.bak\n\ndiff -c $1 $1.bak && rm $1.bak\n"
  },
  {
    "path": "hack/verify-image-match.sh",
    "content": "#!/usr/bin/env bash\n\nexport LC_ALL=C\n\ncp $1 $1.bak\n\n$(dirname \"${BASH_SOURCE}\")/fmt-image-match.sh $1.bak\n\ndiff -c $1 $1.bak && rm $1.bak\n"
  },
  {
    "path": "hack/verify-image.sh",
    "content": "#!/usr/bin/env bash\n\nfile=$1\n\npatch_url=$2\n\nlist=\"\"\nif [[ \"${patch_url}\" == \"\" ]]; then\n    list=$(cat \"${file}\")\nelse \n    cp \"${file}\" \"${file}.bak\"\n    git apply -R <(curl -fsSL \"${patch_url}\") || :\n    list=$(diff --unified \"${file}\" \"${file}.bak\" | grep '^+\\w' | sed 's/^+//' || :)\nfi\n\nfailed=()\nfor image in ${list}; do\n    image=\"${image%%\\:*}\"\n    echo \"Checking image: ${image}\"\n    raw=$(skopeo list-tags --no-creds --tls-verify=false --retry-times 3 \"docker://${image}\")\n    if [[ $? -ne 0 ]]; then\n        failed+=(\"not found ${image}\")\n        echo \"Not found ${image}\"\n        continue\n    fi\n    if [[ $(echo \"${raw}\" | jq '.Tags | length') -eq 0 ]]; then\n        failed+=(\"found ${image} but no tags\")\n        echo \"Found ${image} but no tags\"\n        echo \"${raw}\"\n        continue\n    fi\ndone\n\nif [[ ${#failed[@]} -ne 0 ]]; then\n    echo \"Failed images:\"\n    for image in \"${failed[@]}\"; do\n        echo \"  ${image}\"\n    done\n    exit 1\nfi\n"
  },
  {
    "path": "hack/verify-k8s-prefix.sh",
    "content": "#!/usr/bin/env bash\n\nfile=$1\n\nresult=\"$(cat ${file} | grep k8s.gcr.io/)\"\n\nif [[ \"${result}\" != \"\" ]]; then\n    echo \"Usually registry.k8s.io/* instead of k8s.gcr.io/*\"\n    echo \"Please run following command to fix the issue:\"\n    echo \"cat ${file} | sed 's#k8s.gcr.io/#registry.k8s.io/#' >${file}.bak\"\n    echo \"mv ${file}.bak ${file}\"\n    echo \"./hack/fmt.sh ${file}\"\n\n    exit 1\nfi\n"
  }
]