Full Code of DaoCloud/public-image-mirror for AI

main 2a8b03e4641a cached
29 files
87.5 KB
26.9k tokens
1 requests
Download .txt
Repository: DaoCloud/public-image-mirror
Branch: main
Commit: 2a8b03e4641a
Files: 29
Total size: 87.5 KB

Directory structure:
gitextract_k3b5ogrq/

├── .gitee/
│   └── ISSUE_TEMPLATE/
│       └── allows-image.yml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── allows-image.yml
│   │   └── sync-image.yml
│   └── workflows/
│       ├── ci-bot.yml
│       ├── cidn-runner.yml
│       ├── sync-image.yml
│       ├── update-allows-list.yml
│       └── verify-pr.yml
├── LICENSE
├── README.md
├── allows.txt
├── docs/
│   └── local-cache/
│       └── README.md
└── hack/
    ├── badge.sh
    ├── correct-image.sh
    ├── diff-image.sh
    ├── diff.sh
    ├── fmt-image-match.sh
    ├── fmt-image.sh
    ├── fmt.sh
    ├── helper.sh
    ├── merge-mirror.sh
    ├── stats-not-sync.sh
    ├── verify-allows.sh
    ├── verify-docker-prefix.sh
    ├── verify-fmt-image.sh
    ├── verify-fmt.sh
    ├── verify-image-match.sh
    ├── verify-image.sh
    └── verify-k8s-prefix.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitee/ISSUE_TEMPLATE/allows-image.yml
================================================
name: Allows Image
description: 添加白名单 (人工审核)
labels:
- allows image
body:
- type: markdown
  attributes:
    value: |
      - 对于镜像的要求 [#2328](https://github.com/DaoCloud/public-image-mirror/issues/2328)
      - 一般 5个工作日内 🐢 [查看成功案例](https://github.com/DaoCloud/public-image-mirror/issues?q=is%3Aissue+label%3A%22allows+image%22+is%3Aclosed+linked%3Apr)
      - 自己提 [PR](https://github.com/DaoCloud/public-image-mirror/blob/main/allows.txt) 修改白名单优先审查 🚀
      - 注意在 PR 的内容里描述 Fixed # 这个 issue 的 id [示例](https://github.com/DaoCloud/public-image-mirror/pull/23762)

- type: dropdown
  attributes:
    label: 白名单级别
    options:
    - 只需要这一个镜像 (如 docker.io/library/busybox)
    - 需要这个组织下所有镜像 (如 docker.io/library/*)
  validations:
    required: true

- type: textarea
  attributes:
    label: 镜像仓库地址
    placeholder: |
      https://hub.docker.com/r/...
  validations:
    required: true

- type: dropdown
  attributes:
    label: 这是 **镜像仓库** 认证可信的 **验证过的发布者(Verified Publisher)**或者**赞助的项目(Sponsored OSS)** 么?
    options:
    - 不是 - 请补充下面的信息
    - 是的 - 不需要填下面的信息 - 如果实际上不是将不再继续核查
  validations:
    required: true

- type: textarea
  attributes:
    label: 项目源码地址 或 组织地址
    placeholder: |
      https://github.com/...

- type: textarea
  attributes:
    label: 官网 或 文档 或 项目源码 中哪提及对应的镜像的地址 (需要证明这个镜像和源码有实际关联)

- type: textarea
  attributes:
    label: 补充说明

- type: markdown
  attributes:
    value: |
      有疑问反馈, 请添加我们的企微群 [#4183](https://github.com/DaoCloud/public-image-mirror/issues/4183)


================================================
FILE: .github/ISSUE_TEMPLATE/allows-image.yml
================================================
name: Allows Image
description: 添加白名单 (人工审核)
labels:
- allows image
body:
- type: markdown
  attributes:
    value: |
      - 对于镜像的要求 [#2328](https://github.com/DaoCloud/public-image-mirror/issues/2328)
      - 一般 5个工作日内 🐢 [查看成功案例](https://github.com/DaoCloud/public-image-mirror/issues?q=is%3Aissue+label%3A%22allows+image%22+is%3Aclosed+linked%3Apr)
      - 自己提 [PR](https://github.com/DaoCloud/public-image-mirror/blob/main/allows.txt) 修改白名单优先审查 🚀
      - 注意在 PR 的内容里描述 Fixed # 这个 issue 的 id [示例](https://github.com/DaoCloud/public-image-mirror/pull/23762)

- type: dropdown
  attributes:
    label: 白名单级别
    options:
    - 只需要这一个镜像 (如 docker.io/library/busybox)
    - 需要这个组织下所有镜像 (如 docker.io/library/*)
  validations:
    required: true

- type: textarea
  attributes:
    label: 镜像仓库地址
    placeholder: |
      https://hub.docker.com/r/...
  validations:
    required: true

- type: dropdown
  attributes:
    label: 这是 **镜像仓库** 认证可信的 **验证过的发布者(Verified Publisher)**或者**赞助的项目(Sponsored OSS)** 么?
    options:
    - 不是 - 请补充下面的信息
    - 是的 - 不需要填下面的信息 - 如果实际上不是将不再继续核查
  validations:
    required: true

- type: textarea
  attributes:
    label: 项目源码地址 或 组织地址
    placeholder: |
      https://github.com/...

- type: textarea
  attributes:
    label: 官网 或 文档 或 项目源码 中哪提及对应的镜像的地址 (需要证明这个镜像和源码有实际关联)

- type: textarea
  attributes:
    label: 补充说明

- type: markdown
  attributes:
    value: |
      有疑问反馈, 请添加我们的企微群 [#4183](https://github.com/DaoCloud/public-image-mirror/issues/4183)


================================================
FILE: .github/ISSUE_TEMPLATE/sync-image.yml
================================================
name: Sync Image
description: 同步一个镜像 (需要 Image 已在白名单里)
labels:
- sync image
body:
- type: markdown
  attributes:
    value: |
      # ↑↑↑↑↑↑↑↑↑↑↑ 填入你要同步的 Image
      ## 请包含 域名/路径:标签

- type: dropdown
  attributes:
    label: 镜像架构
    description: 请选择要同步的目标架构
    options:
    - linux/amd64
    - linux/386
    - linux/arm64
    - linux/arm/v6
    - linux/arm/v7
    - linux/ppc64le
    - linux/s390x
  validations:
    required: true

- type: markdown
  attributes:
    value: |
      请确保包含域名(domain)
      - 如 docker.io/
      - 如 registry.k8s.io/
      - 如果不包含域名, 需要主动添加默认的 docker.io/

- type: markdown
  attributes:
    value: |
      请确保包含镜像的标签(tag)
      - 如 :latest
      - 如 :v1

- type: markdown
  attributes:
    value: |
      请确保这个镜像真实存在
      - 如 docker.io/library/busybox:latest
      - 如 docker.io/kindest/node:v1.30.0
      - 如 registry.k8s.io/kubectl:v1.30.0

- type: markdown
  attributes:
    value: |
      有疑问反馈, 请添加我们的企微群 [#4183](https://github.com/DaoCloud/public-image-mirror/issues/4183)


================================================
FILE: .github/workflows/ci-bot.yml
================================================
name: CI Bot
on:
  issue_comment:
    types:
      - created

  pull_request_review_comment:
    types:
      - created

  issues:
    types:
      - opened

  # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
  pull_request_target:
    types:
      - opened

env:
  # This plugins is for anyone who can use it
  PLUGINS: |-
    assign
    auto-cc
    cc

  # This plugins is for author of issue or PR
  AUTHOR_PLUGINS: |-
    label-bug
    label-documentation
    label-enhancement
    label-question
    retest

  # This plugins is for organization member or repository member
  MEMBERS_PLUGINS: |-
    label-duplicate
    label-good-first-issue
    label-help-wanted
    label-invalid
    label-kind
    label-wontfix
    label-bug
    label-documentation
    label-enhancement
    label-question
    lifecycle
    retest

  # This plugins is for in the REVIEWERS environment variable
  REVIEWERS_PLUGINS: |-
    label-lgtm
    retitle

  # This plugins is for in the APPROVERS environment variable
  APPROVERS_PLUGINS: |-
    label
    merge
    base
    rebase

  # This plugins is for in the MAINTAINERS environment variable
  MAINTAINERS_PLUGINS: |-
    milestone

  # This plugins is for organization owner or repository owner
  OWNERS_PLUGINS: ""

  REVIEWERS: |-
    yankay
    wzshiming
  APPROVERS: |-
    yankay
    wzshiming
  MAINTAINERS: |-
    yankay
    wzshiming

  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  GH_REPOSITORY: ${{ github.repository }}
  DETAILS: |-

    <details>
    <summary>Details</summary>

    Instructions for interacting with me using comments are available here.
    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.

    </details>

# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
permissions:
  actions: write
  checks: read
  contents: write
  deployments: none
  id-token: none
  issues: write
  discussions: read
  packages: none
  pages: none
  pull-requests: write
  repository-projects: read
  security-events: none
  statuses: read

jobs:
  bot:
    name: Bot
    runs-on: ubuntu-latest
    steps:
      - name: Issue Opened
        uses: wzshiming/gh-ci-bot@v1
        if: ${{ github.event_name == 'issues' }}
        env:
          LOGIN: ${{ github.event.issue.user.login }}
          AUTHOR: ${{ github.event.issue.user.login }}
          MESSAGE: ${{ github.event.issue.body }}
          ISSUE_NUMBER: ${{ github.event.issue.number }}
          AUTHOR_ASSOCIATION: ${{ github.event.issue.author_association }}
          ISSUE_KIND: issue
          TYPE: created
          GREETING: |-
            Hi @${{ github.event.issue.user.login }},
            感谢您的反馈!
            我们会尽快跟进.

      - name: PR Opened
        uses: wzshiming/gh-ci-bot@v1
        if: ${{ github.event_name == 'pull_request_target' }}
        env:
          LOGIN: ${{ github.event.pull_request.user.login }}
          AUTHOR: ${{ github.event.pull_request.user.login }}
          MESSAGE: ${{ github.event.pull_request.body }}
          ISSUE_NUMBER: ${{ github.event.pull_request.number }}
          AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association }}
          ISSUE_KIND: pr
          TYPE: created
          GREETING: |-
            Hi @${{ github.event.pull_request.user.login }},
            感谢您的 PR !
            如果 PR 已经准备就绪可以 `/auto-cc` ,我们会尽快跟进.

      - name: Issue Commented
        uses: wzshiming/gh-ci-bot@v1
        if: ${{ github.event_name == 'issue_comment' && !github.event.issue.pull_request }}
        env:
          LOGIN: ${{ github.event.comment.user.login }}
          AUTHOR: ${{ github.event.issue.user.login }}
          MESSAGE: ${{ github.event.comment.body }}
          ISSUE_NUMBER: ${{ github.event.issue.number }}
          AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}
          ISSUE_KIND: issue
          TYPE: comment

      - name: PR Review Commented
        uses: wzshiming/gh-ci-bot@v1
        if: ${{ github.event_name == 'pull_request_review_comment' }}
        env:
          LOGIN: ${{ github.event.comment.user.login }}
          AUTHOR: ${{ github.event.pull_request.user.login }}
          MESSAGE: ${{ github.event.comment.body }}
          ISSUE_NUMBER: ${{ github.event.pull_request.number }}
          AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}
          ISSUE_KIND: pr
          TYPE: comment

      - name: PR Commented
        uses: wzshiming/gh-ci-bot@v1
        if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request }}
        env:
          LOGIN: ${{ github.event.comment.user.login }}
          AUTHOR: ${{ github.event.issue.user.login }}
          MESSAGE: ${{ github.event.comment.body }}
          ISSUE_NUMBER: ${{ github.event.issue.number }}
          AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}
          ISSUE_KIND: pr
          TYPE: comment


================================================
FILE: .github/workflows/cidn-runner.yml
================================================
name: CIDN Runner
run-name: CIDN Runner ${{ github.run_number }}

on:
  schedule:
    - cron: "0,30 * * * *"

  workflow_dispatch:

jobs:
  runner:
    runs-on: ubuntu-latest
    if: github.repository == 'DaoCloud/public-image-mirror'
    container: ghcr.io/opencidn/cidn/runner:v0.0.109
    steps:
    - shell: sh
      run: runner --handler-name=dc-${{ github.run_number }} --update-duration=10s --duration=4h --concurrency=3 ${{ secrets.ARGS_CIDN }}


================================================
FILE: .github/workflows/sync-image.yml
================================================
name: Target Sync Image
run-name: Target Sync ${{ github.event.issue.title }} by @${{ github.actor }}

on:
  issues:
    types:
      - opened

# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
permissions:
  issues: write

jobs:
  check:
    runs-on: ubuntu-latest
    if: contains(github.event.issue.labels.*.name, 'sync image')
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    outputs:
      image: ${{ steps.get-image.outputs.image }}
      link: ${{ steps.get-image.outputs.link }}
      platforms: ${{ steps.get-image.outputs.platforms }}
      arch: ${{ steps.get-image.outputs.arch }}
    steps:
    - name: Checkout repository
      uses: actions/checkout@v4
    - name: Check Issue
      id: get-image
      env:
        IMAGE: "${{ github.event.issue.title }}"
        ISSUE_BODY: "${{ github.event.issue.body }}"
      run: |
        ORIGIN_IMAGE="${IMAGE}"
        CORRECT_IMAGE="$(./hack/correct-image.sh "${ORIGIN_IMAGE}")"
        if [[ "${CORRECT_IMAGE}" == "" ]]; then
          gh issue comment ${{ github.event.issue.number }} -b "镜像 '${ORIGIN_IMAGE}' 不是一个镜像"
          gh issue close ${{ github.event.issue.number }} --reason "not planned"
          exit 1
        fi
        if [[ "${CORRECT_IMAGE}" != "${ORIGIN_IMAGE}" ]]; then
          if ! ./hack/verify-allows.sh ./allows.txt "${CORRECT_IMAGE}"; then
            gh issue comment ${{ github.event.issue.number }} -b "镜像 '${ORIGIN_IMAGE}' 不存在呢, 也许应该是 '${CORRECT_IMAGE}', 并且不在白名单列表里, 不支持同步和访问<br>可以将其添加到[白名单](https://github.com/${{ github.repository }}/issues/2328)"
          else
            gh issue comment ${{ github.event.issue.number }} -b "镜像 '${ORIGIN_IMAGE}' 不存在呢, 也许应该是 '${CORRECT_IMAGE}'"
          fi
          gh issue close ${{ github.event.issue.number }} --reason "not planned"
          exit 1
        fi
        if ! ./hack/verify-allows.sh ./allows.txt "${ORIGIN_IMAGE}"; then
          gh issue comment ${{ github.event.issue.number }} -b "镜像 ${ORIGIN_IMAGE} 不在白名单列表里, 不支持同步和访问<br>可以将其添加到[白名单](https://github.com/${{ github.repository }}/issues/2328)"
          gh issue close ${{ github.event.issue.number }} --reason "not planned"
          exit 1
        fi

        IMAGE="${ORIGIN_IMAGE}"
        echo "image=${IMAGE}" >> $GITHUB_OUTPUT
        GROUP="${IMAGE%%:*}"
        GROUP="${GROUP%%@*}"
        LINK="https://queue.m.daocloud.io/status/#group:${GROUP}"
        echo "link=${LINK}" >> $GITHUB_OUTPUT

        BODY="${ISSUE_BODY:-}"
        ARCH=""

        if [ -z "${ARCH}" ]; then
          ARCH=$(printf "%s" "$BODY" | grep -oE 'linux/[a-z0-9/._+-]+' | head -n1 || true)
        fi

        if [ -z "${ARCH}" ]; then
          ARCH="linux/amd64"
        fi

        echo "arch=${ARCH}" >> $GITHUB_OUTPUT

        PLATFORM_FLAG="--platform=${ARCH}"
        echo "platforms=${PLATFORM_FLAG}" >> $GITHUB_OUTPUT

        gh issue comment ${{ github.event.issue.number }} -b "镜像 ${IMAGE}, 平台 ${ARCH} 将添加到同步队列...<br>[同步队列](${LINK})<br>[详细信息](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})"

  sync:
    runs-on: ubuntu-latest
    needs: check
    if: needs.check.result == 'success'
    container: ghcr.io/opencidn/ocimirror/sync:v0.0.40
    steps:
    - shell: sh
      run: sync ${{ needs.check.outputs.image }} ${{ needs.check.outputs.platforms }} ${{ secrets.ARGS_CIDN }} ${{ secrets.ARGS_R2_IMAGE }}

  runner:
    runs-on: ubuntu-latest
    needs: check
    if: needs.check.result == 'success'
    container: ghcr.io/opencidn/cidn/runner:v0.0.108
    steps:
    - shell: sh
      run: runner --handler-name=dc-${{ github.run_number }}-${{ github.event.issue.number }} --update-duration=10s --duration=5m --concurrency=2 ${{ secrets.ARGS_CIDN }}

  failure:
    runs-on: ubuntu-latest
    needs:
    - sync
    - check
    if: always() && needs.sync.result == 'failure'
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
    - name: Sync Failure Status
      run: |
        gh -R "${{ github.repository }}" issue edit ${{ github.event.issue.number }} --add-label "sync image failure" -b "镜像同步失败"
        gh -R "${{ github.repository }}" issue close ${{ github.event.issue.number }} --reason "not planned" --comment "镜像 ${{ needs.check.outputs.image }}, 平台 ${{ needs.check.outputs.arch }} 同步失败<br>请去同步队列查看详细信息。"
  
  success:
    runs-on: ubuntu-latest
    needs:
    - sync
    - check
    if: needs.sync.result == 'success'
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
    - name: Sync Success Status
      run: |
        gh -R "${{ github.repository }}" issue edit ${{ github.event.issue.number }} --add-label "sync image succeeded" -b "镜像同步完成"
        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 }} 进行访问。"


================================================
FILE: .github/workflows/update-allows-list.yml
================================================
name: Update allows list

on:
  push:
    paths:
    - allows.txt
    branches:
    - main
  workflow_dispatch:

jobs:
  update-allows-list:
    if: github.repository == 'DaoCloud/public-image-mirror'
    runs-on: ubuntu-latest
    steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    - name: Update list
      run: |
        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."}')"
        TOKEN="$(curl -X 'POST' \
          'https://queue.m.daocloud.io/apis/auth/users/login' \
          -H 'Accept: application/json' \
          -H 'Content-Type: application/json' \
          -d ${{ secrets.USER_LOGIN_DATA }} | jq -r .token)"
        curl -f -X 'PUT' \
          'https://queue.m.daocloud.io/apis/auth/registries/allow_images' \
          -H 'Accept: application/json' \
          -H "Authorization: Bearer ${TOKEN}" \
          -H 'Content-Type: application/json' \
          -d "${LIST}"


================================================
FILE: .github/workflows/verify-pr.yml
================================================
name: Verify PR

on:
  pull_request_target:
    branches: [main]
    paths:
      - 'mirror.txt'
      - 'allows.txt'

permissions:
  issues: write
  pull-requests: write

env:
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
  verify-pr:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Commit PR
        run: |
          git config --global user.name "github-actions[bot]"
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
          wget -O pr.patch https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}.patch && \
            git am -3 pr.patch &&
            rm -rf pr.patch

      - name: Verify allows.txt sort
        run: |
          ./hack/verify-image-match.sh allows.txt || {
            echo "Please run './hack/fmt-image-match.sh allows.txt'"
            gh pr comment "${{ github.event.pull_request.number }}" --body '请运行 `./hack/fmt-image-match.sh allows.txt` 对内容进行排序'
            exit 1
          }


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
# public-image-mirror

源仓库 [Github](https://github.com/DaoCloud/public-image-mirror)  
Mirror 仓库 [Gitee](https://gitee.com/daocloud/public-image-mirror)  

- 白名单 & 限流 的公开信息 [#2328](https://github.com/DaoCloud/public-image-mirror/issues/2328)
- 如有疑问请咨询 [#4183](https://github.com/DaoCloud/public-image-mirror/issues/4183)
- 建议将拉取任务放在闲时 凌晨(北京时间 01-07 点), 其他时间段非常拥挤
- 建议使用明确版本号的 tag, 对于 latest 这种变更后响应旧数据, 并且后台重新同步
- [本服务后端代码](https://github.com/OpenCIDN/ocimirror)
- [同步队列](https://queue.m.daocloud.io/status/) 仅保留一小时的同步记录
- [服务状态监控](https://status.daocloud.io/status/docker)

## 背景 & 目标

很多镜像都在国外。比如 gcr 。国内下载很慢,需要加速。

* 一个简洁有效的方法能够加速这些包。简洁的名称映射
* 易于添加,添加新的包,不需要去修改代码。
* 稳定可靠,更新实时。每天检查同步情况。
* 此项目仅是源镜像仓库 (Registry) 的 Mirror
  * 所有 hash(sha256) 均和源保持一致 (懒加载机制)。
  * 缓存的内容只保留 90 天, 过期后会需要重新同步。
  * Manifest 内存缓存 1 小时, 所以 tag 被更新了 1 小时之后才会同步新的。
  * Blob 内存缓存 1 分钟, 在期间如果 blob 到达 90 天期限被删除会报 404。

## 快速开始

```
docker run -d -P m.daocloud.io/docker.io/library/nginx
```
## 使用方法

**增加前缀** (推荐方式)。比如:

``` log
              docker.io/library/busybox
                 |
                 V
m.daocloud.io/docker.io/library/busybox
```

或者 支持的镜像仓库 的 *前缀替换* 就可以使用。比如:

``` log
           docker.io/library/busybox
             |
             V
docker.m.daocloud.io/library/busybox
```

## 支持前缀替换的 Registry (不推荐)

推荐使用添加前缀的方式.

前缀替换的 Registry 的规则, 这是人工配置的, 有需求提 Issue.

除了 docker.io 这里每一个源站, 内容都是不同的, 不要把 docker.io 之外的站点配置给 registry-mirrors

| 源站               | 替换为                | 备注                                           |
| ------------------ | --------------------- | ---------------------------------------------- |
| docker.elastic.co  | elastic.m.daocloud.io |                                                |
| docker.io          | docker.m.daocloud.io  |                                                |
| dhi.io             | dhi.m.daocloud.io     |                                                |
| gcr.io             | gcr.m.daocloud.io     |                                                |
| ghcr.io            | ghcr.m.daocloud.io    |                                                |
| k8s.gcr.io         | k8s-gcr.m.daocloud.io | k8s.gcr.io 已被迁移到 registry.k8s.io          |
| registry.k8s.io    | k8s.m.daocloud.io     |                                                |
| mcr.microsoft.com  | mcr.m.daocloud.io     |                                                |
| nvcr.io            | nvcr.m.daocloud.io    |                                                |
| quay.io            | quay.m.daocloud.io    |                                                |
| registry.ollama.ai | ollama.m.daocloud.io  | 实验内测中,[使用方法](#加速-ollama--deepseek) |

## 最佳实践

### 部署内网缓存

本地缓存部署用于在内网环境中加速镜像拉取,减少对外网的依赖。通过设置一个本地镜像仓库,您可以缓存常用的镜像。
[请参考文档](https://github.com/DaoCloud/public-image-mirror/tree/main/docs/local-cache)

### 加速 Kubneretes

#### 加速安装 kubeadm

``` yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
dns:
  imageRepository: k8s.m.daocloud.io/coredns
imageRepository: k8s.m.daocloud.io
...
```

#### 加速安装 kind

``` bash
kind create cluster --name kind --image m.daocloud.io/docker.io/kindest/node:v1.22.1
```

#### 加速所有 Pod

https://github.com/wzshiming/repimage

不修改 yaml, helm 等, 仅使用 Webhook, 自动修改所有新建 Pod 的 image 使用本 mirror

``` bash
kubectl create -f https://files.m.daocloud.io/github.com/wzshiming/repimage/releases/download/latest/repimage.yaml
kubectl rollout status deployment/repimage -n kube-system
```

#### 加速 Containerd

* 参考 Containerd 官方文档: [hosts.md](https://github.com/containerd/containerd/blob/main/docs/hosts.md#registry-host-namespace)
* 如果您使用 kubespray 安装 containerd, 可以配置 [`containerd_registries_mirrors`](https://github.com/kubernetes-sigs/kubespray/blob/master/docs/CRI/containerd.md#containerd-config)

### 加速 Docker

添加到 `/etc/docker/daemon.json`
``` json
{
  "registry-mirrors": [
    "https://docker.m.daocloud.io"
  ]
}
```

### 加速 Ollama & DeepSeek

#### 加速安装 Ollama

CPU:
```bash
docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama docker.m.daocloud.io/ollama/ollama
```

GPU 版本:
1. 首先安装 Nvidia Container Toolkit
2. 运行以下命令启动 Ollama 容器:

```bash
docker run -d --gpus=all -v ollama:/root/.ollama -p 11434:11434 --name ollama docker.m.daocloud.io/ollama/ollama
```

更多信息请参考:
* [Ollama Docker 官方文档](https://ollama.com/blog/ollama-is-now-available-as-an-official-docker-image)

#### 加速使用 Deepseek-R1 模型(实验内测中)

如上述步骤,在启动了ollama容器的前提下,还可以通过加速源,加速启动DeepSeek相关的模型服务

注:目前 Ollama 官方源的下载速度已经很快,您也可以直接使用[官方源](https://ollama.com/library/deepseek-r1:1.5b)。

```bash
# 使用加速源
docker exec -it ollama ollama run ollama.m.daocloud.io/library/deepseek-r1:1.5b

# 或直接使用官方源下载模型
# docker exec -it ollama ollama run deepseek-r1:1.5b
```

## [友情链接]加速二剑客

* 镜像加速:https://github.com/DaoCloud/public-image-mirror
* 二进制文件加速:https://github.com/DaoCloud/public-binary-files-mirror

## 贡献者

<a href="https://github.com/DaoCloud/public-image-mirror/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=DaoCloud/public-image-mirror" />
</a>

Made with [contrib.rocks](https://contrib.rocks).


================================================
FILE: allows.txt
================================================
code.forgejo.org/forgejo/forgejo
code.forgejo.org/forgejo/runner
codeberg.org/forgejo/forgejo
container-registry.oracle.com/**
cr.kgateway.dev/kgateway-dev/*
cr.l5d.io/**
cr.weaviate.io/**
dhi.io/**
docker.com/kyantech/*
docker.elastic.co/**
docker.getcollate.io/openmetadata/*
docker.io/*
docker.io/0nlylty/dockercopilot
docker.io/1activegeek/airconnect
docker.io/1dev/*
docker.io/1panel/maxkb
docker.io/4pdosc/k8s-vdevice
docker.io/569107519/alertsnitch-mysql
docker.io/6053537/portainer-ce
docker.io/acim/go-reflex
docker.io/acore/*
docker.io/acryldata/*
docker.io/adguard/adguardhome
docker.io/adoptopenjdk/*
docker.io/adriansegura99/**
docker.io/agentaai/*
docker.io/ai/*
docker.io/alexxit/go2rtc
docker.io/alexzhc/*
docker.io/allanpk716/chinesesubfinder
docker.io/allfunc/speedtest
docker.io/almalinux/*
docker.io/alpine/*
docker.io/alpinelinux/**
docker.io/alseambusher/crontab-ui
docker.io/altinity/*
docker.io/amambadev/*
docker.io/amazon/*
docker.io/amd64/*
docker.io/amir20/*
docker.io/amtoaer/bili-sync-rs
docker.io/andrejorsula/space_robotics_bench
docker.io/andywuwu/coze2openai
docker.io/ankane/pgvector
docker.io/apache/*
docker.io/apachepulsar/*
docker.io/apacherocketmq/*
docker.io/apecloud/*
docker.io/apereo/cas
docker.io/apicurio/*
docker.io/apipark/apipark
docker.io/apitable/*
docker.io/apolloconfig/*
docker.io/appbaseio/dejavu
docker.io/approachingai/*
docker.io/appsmith/appsmith-ce
docker.io/appsmith/appsmith-ee
docker.io/aquasec/*
docker.io/arexadmin01/*
docker.io/arey/*
docker.io/argoproj/rollouts-demo
docker.io/arigaio/*
docker.io/arizephoenix/phoenix
docker.io/arm64v8/*
docker.io/artalk/artalk-go
docker.io/ascendai/*
docker.io/ascentstream/*
docker.io/astral/uv
docker.io/atlassian/*
docker.io/authelia/authelia
docker.io/automatischio/automatisch
docker.io/autumn27/scopesentry-scan
docker.io/b3log/siyuan
docker.io/babashka/babashka
docker.io/basecamp/*
docker.io/bats/*
docker.io/bellsoft/*
docker.io/benzino77/clamav-rest-api
docker.io/bililive/recorder
docker.io/binhex/arch-jellyfin
docker.io/binwiederhier/ntfy
docker.io/bitnami/*
docker.io/bitnamicharts/*
docker.io/bitnamilegacy/*
docker.io/bluenviron/mediamtx
docker.io/boky/postfix
docker.io/boredazfcuk/icloudpd
docker.io/browserless/*
docker.io/browsh/browsh
docker.io/budibase/budibase
docker.io/budtmo/docker-android
docker.io/burakince/mlflow
docker.io/bvlc/caffe
docker.io/bytebase/bytebase
docker.io/bytelang/kplayer
docker.io/caarlos0/domain_exporter
docker.io/calciumion/new-api
docker.io/calico/*
docker.io/camunda/zeebe
docker.io/canal/canal-server
docker.io/caronc/apprise
docker.io/cars10/elasticvue
docker.io/casbin/casdoor
docker.io/certbot/*
docker.io/chaosbladeio/chaosblade-box
docker.io/chaoszhu/easynode
docker.io/charlie0129/bupt-net-login
docker.io/chat2db/chat2db
docker.io/chatimage/chatchat
docker.io/chatwoot/chatwoot
docker.io/chengshiwen/influx-proxy
docker.io/chengshiwen/influxdb
docker.io/chenhw2/aliyun-ddns-cli
docker.io/chigusa/bililive-go
docker.io/chirpstack/*
docker.io/chishin/nginx-proxy-manager-zh
docker.io/chrishirsch/kuberhealthy-storage-check
docker.io/chrislusf/seaweedfs
docker.io/chromedp/headless-shell
docker.io/chrstnhntschl/gpu_burn
docker.io/cimg/go
docker.io/clamav/*
docker.io/claraverse/clara-ollama
docker.io/clickhouse/*
docker.io/clidey/whodb
docker.io/cloudflare/*
docker.io/cloudnas/clouddrive2-unstable
docker.io/cloudnativelabs/kube-router
docker.io/cloudreve/cloudreve
docker.io/codercom/code-server
docker.io/codewisdom/*
docker.io/collabora/code
docker.io/condaforge/miniforge3
docker.io/conduktor/*
docker.io/confluentinc/*
docker.io/containrrr/watchtower
docker.io/continuumio/miniconda3
docker.io/coredns/*
docker.io/coturn/coturn
docker.io/cozedev/*
docker.io/cp2k/cp2k
docker.io/csiplugin/*
docker.io/cturra/ntp
docker.io/curlimages/*
docker.io/cvat/server
docker.io/cvat/ui
docker.io/cym1102/nginxwebui
docker.io/czerwonk/ping_exporter
docker.io/dadoum/anisette-v3-server
docker.io/dani-garcia/vaultwarden
docker.io/danielqsj/kafka-exporter
docker.io/daprio/*
docker.io/darthsim/imgproxy
docker.io/dataease/sqlbot
docker.io/datastax/*
docker.io/dbeaver/cloudbeaver
docker.io/debezium/*
docker.io/deepflowce/*
docker.io/deluan/navidrome
docker.io/democraticcsi/csi-grpc-proxy
docker.io/democraticcsi/democratic-csi
docker.io/denoland/deno
docker.io/derailed/k9s
docker.io/determinedai/*
docker.io/devicefarmer/stf
docker.io/dezhao/lanraragi_cn
docker.io/difegue/lanraragi
docker.io/digitalocean/ceph_exporter
docker.io/directus/*
docker.io/discourse/*
docker.io/diygod/*
docker.io/docker/*
docker.io/dockurr/*
docker.io/dokploy/*
docker.io/doocs/*
docker.io/dorowu/ubuntu-desktop-lxde-vnc
docker.io/dpage/*
docker.io/dpanel/base-image
docker.io/dpanel/dpanel
docker.io/dragonflydb/dragonfly
docker.io/dragonflyoss/client
docker.io/dragonflyoss/dfdaemon
docker.io/dragonflyoss/dfinit
docker.io/dragonflyoss/manager
docker.io/dragonflyoss/scheduler
docker.io/dragonflyoss/trainer
docker.io/drakkan/sftpgo
docker.io/dreamacro/clash
docker.io/dremio/dremio-oss
docker.io/drone/drone
docker.io/drone/drone-runner-docker
docker.io/drumsergio/genieacs
docker.io/duckdb/duckdb
docker.io/dushixiang/kafka-map
docker.io/dustynv/*
docker.io/dxflrs/*
docker.io/e2bdev/code-interpreter
docker.io/easytier/easytier
docker.io/elastic/*
docker.io/electronuserland/builder
docker.io/elestio/neko
docker.io/eloqdata/*
docker.io/elsaworkflows/*
docker.io/emberstack/kubernetes-reflector
docker.io/emby/*
docker.io/emqx/*
docker.io/enable/nessus
docker.io/ensemblorg/ensembl-vep
docker.io/envoyproxy/*
docker.io/eolinker/apinto-gateway
docker.io/eosphorosai/*
docker.io/esphome/*
docker.io/estrellaxd/auto_bangumi
docker.io/eucm/limesurvey
docker.io/exadel/compreface-core
docker.io/exceptionless/*
docker.io/eyeblue/tank
docker.io/f5networks/*
docker.io/falcosecurity/*
docker.io/falkordb/falkordb
docker.io/fatedier/frps
docker.io/feiyu563/prometheus-alert
docker.io/feiyuyu/filecodebox
docker.io/ffdfgdfg/npc
docker.io/ffdfgdfg/nps
docker.io/fffaraz/fakessh
docker.io/filebrowser/filebrowser
docker.io/finab/bark-server
docker.io/firecow/gitlab-ci-local-util
docker.io/fireflyiii/*
docker.io/flannel/*
docker.io/flannelcni/*
docker.io/flashcatcloud/*
docker.io/flexget/flexget
docker.io/floryn90/hugo
docker.io/flowiseai/flowise
docker.io/fluent/*
docker.io/flyway/flyway
docker.io/forceless/pptagent
docker.io/fortio/*
docker.io/fosrl/*
docker.io/foxdalas/*
docker.io/frappe/*
docker.io/freeradius/freeradius-server
docker.io/freesurfer/synthmorph
docker.io/frooodle/s-pdf
docker.io/frrouting/*
docker.io/funcman/115pc
docker.io/gaecfovdocker/pulsar-console
docker.io/gchq/hdfs
docker.io/geoservercloud/*
docker.io/germannewsmaker/myspeed
docker.io/gerritcodereview/gerrit
docker.io/getmeili/*
docker.io/getsentry/*
docker.io/getwud/wud
docker.io/gitea/*
docker.io/gitlab/*
docker.io/gitpod/openvscode-server
docker.io/gliderlabs/logspout
docker.io/goacme/lego
docker.io/gocd/*
docker.io/gogs/gogs
docker.io/goharbor/*
docker.io/golangci/golangci-lint
docker.io/google/*
docker.io/goproxy/goproxy
docker.io/goreleaser/goreleaser
docker.io/gotenberg/gotenberg
docker.io/gotify/*
docker.io/gotson/komga
docker.io/gpustack/gpustack
docker.io/gpustack/runner
docker.io/grafana/*
docker.io/graphiteapp/graphite-statsd
docker.io/gravitl/netmaker
docker.io/graylog/graylog
docker.io/graylog/graylog-datanode
docker.io/greatsql/*
docker.io/greenbone/*
docker.io/greper/certd
docker.io/guacamole/*
docker.io/guiji2025/*
docker.io/gztime/gzctf
docker.io/hacdias/webdav
docker.io/hagb/docker-easyconnect
docker.io/hakuyyf/tensorrtx
docker.io/halohub/halo
docker.io/hanxi/xiaomusic
docker.io/haproxytech/*
docker.io/harness/*
docker.io/haroldli/xiaoya-tvbox
docker.io/hashicorp/*
docker.io/headscale/headscale
docker.io/heartexlabs/label-studio
docker.io/heartexlabs/label-studio-ml-backend
docker.io/hectorqin/reader
docker.io/hengyunabc/arthas
docker.io/henrygd/beszel
docker.io/henrygd/beszel-agent
docker.io/heroiclabs/nakama-pluginbuilder
docker.io/hewenyulucky/*
docker.io/hivemq/*
docker.io/hiyouga/llamafactory
docker.io/hiyouga/pytorch
docker.io/hiyouga/verl
docker.io/hkalexling/mango
docker.io/homeassistant/*
docker.io/hoppscotch/hoppscotch
docker.io/hpcaitech/colossalai
docker.io/hpcaitech/pytorch-cuda
docker.io/hslr/sun-panel
docker.io/huggingface/*
docker.io/hugomods/hugo
docker.io/hummingbot/hummingbot
docker.io/hybridnetdev/hybridnet
docker.io/hyperf/hyperf
docker.io/hyperledger/*
docker.io/hystax/error_pages_base
docker.io/ianw/quickchart
docker.io/ibmcom/*
docker.io/idootop/mi-gpt
docker.io/ihmily/douyin-live-recorder
docker.io/imaegoo/twikoo
docker.io/infiniflow/*
docker.io/infmonkeys/*
docker.io/innei/mx-server
docker.io/instrumentisto/coturn
docker.io/intel/*
docker.io/intelanalytics/*
docker.io/islandora/code-server
docker.io/istio/*
docker.io/itzg/minecraft-server
docker.io/iyuucn/iyuuplus
docker.io/iyuucn/iyuuplus-dev
docker.io/jaegertracing/*
docker.io/jasonrivers/nagios
docker.io/jboss/*
docker.io/jc21/nginx-proxy-manager
docker.io/jeessy/ddns-go
docker.io/jellyfin/*
docker.io/jenkins/*
docker.io/jenkinsci/*
docker.io/jericx/syncclipboard-server
docker.io/jetbrains/*
docker.io/jettech/*
docker.io/jgraph/drawio
docker.io/jimmidyson/*
docker.io/jitesoft/lighttpd
docker.io/jitsi/*
docker.io/jlesage/firefox
docker.io/jlesage/handbrake
docker.io/jmal/jmalcloud
docker.io/john119/vlm
docker.io/johngong/calibre-web
docker.io/joinsunsoft/docker.ui
docker.io/joplin/server
docker.io/joseluisq/static-web-server
docker.io/joxit/docker-registry-ui
docker.io/juicedata/*
docker.io/jumpserver/*
docker.io/jupyter/*
docker.io/jupyterhub/*
docker.io/justarchi/archisteamfarm
docker.io/justlikemaki/openclaw-docker-cn-im
docker.io/justsong/one-api
docker.io/jvmilazz0/kavita
docker.io/jxxghp/*
docker.io/k8scloudprovider/*
docker.io/kafbat/kafka-ui
docker.io/kalilinux/*
docker.io/kanidm/*
docker.io/karmada/*
docker.io/kasmweb/*
docker.io/keelhq/keel
docker.io/keking/kkfileview
docker.io/kennethreitz/*
docker.io/kestra/kestra
docker.io/keycloak/keycloak
docker.io/kicbase/*
docker.io/kindest/*
docker.io/kiwigrid/*
docker.io/klakegg/hugo
docker.io/klausmeyer/docker-registry-browser
docker.io/koalaman/shellcheck
docker.io/koenkk/zigbee2mqtt
docker.io/koide3/direct_visual_lidar_calibration
docker.io/koishijs/koishi
docker.io/kong/*
docker.io/kserve/*
docker.io/kspacekelvin/fire-python
docker.io/kubeedge/*
docker.io/kubeflow/*
docker.io/kubeflowkatib/*
docker.io/kubeflownotebookswg/*
docker.io/kubeovn/kube-ovn
docker.io/kuberhealthy/*
docker.io/kubernetesui/*
docker.io/kubeshark/*
docker.io/kubeskoop/*
docker.io/kubesphere/*
docker.io/kubespheredev/ksv-installer
docker.io/kusionstack/*
docker.io/labring/kubernetes
docker.io/langchain/langgraph-api
docker.io/langflowai/langflow
docker.io/langflowai/langflow-frontend
docker.io/langfuse/*
docker.io/langgenius/*
docker.io/langhuihui/monibuca
docker.io/laradock/*
docker.io/letta/letta
docker.io/lfedge/ekuiper
docker.io/lfnovo/open_notebook
docker.io/liangjw/kube-webhook-certgen
docker.io/library/adminer
docker.io/library/aerospike
docker.io/library/almalinux
docker.io/library/alpine
docker.io/library/alt
docker.io/library/amazoncorretto
docker.io/library/amazonlinux
docker.io/library/api-firewall
docker.io/library/arangodb
docker.io/library/archlinux
docker.io/library/backdrop
docker.io/library/bash
docker.io/library/bonita
docker.io/library/buildpack-deps
docker.io/library/busybox
docker.io/library/caddy
docker.io/library/cassandra
docker.io/library/centos
docker.io/library/chronograf
docker.io/library/cirros
docker.io/library/clearlinux
docker.io/library/clefos
docker.io/library/clickhouse
docker.io/library/clojure
docker.io/library/composer
docker.io/library/consul
docker.io/library/convertigo
docker.io/library/couchbase
docker.io/library/couchdb
docker.io/library/crate
docker.io/library/dart
docker.io/library/debian
docker.io/library/docker
docker.io/library/drupal
docker.io/library/eclipse-mosquitto
docker.io/library/eclipse-temurin
docker.io/library/eggdrop
docker.io/library/elasticsearch
docker.io/library/elixir
docker.io/library/emqx
docker.io/library/erlang
docker.io/library/express-gateway
docker.io/library/fedora
docker.io/library/flink
docker.io/library/fluentd
docker.io/library/friendica
docker.io/library/gazebo
docker.io/library/gcc
docker.io/library/geonetwork
docker.io/library/ghost
docker.io/library/golang
docker.io/library/gradle
docker.io/library/groovy
docker.io/library/haproxy
docker.io/library/haskell
docker.io/library/haxe
docker.io/library/hello-world
docker.io/library/hitch
docker.io/library/httpd
docker.io/library/hylang
docker.io/library/ibm-semeru-runtimes
docker.io/library/ibmjava
docker.io/library/influxdb
docker.io/library/irssi
docker.io/library/java
docker.io/library/jetty
docker.io/library/jobber
docker.io/library/joomla
docker.io/library/jruby
docker.io/library/julia
docker.io/library/kapacitor
docker.io/library/kibana
docker.io/library/kong
docker.io/library/lightstreamer
docker.io/library/liquibase
docker.io/library/logstash
docker.io/library/mageia
docker.io/library/mariadb
docker.io/library/matomo
docker.io/library/maven
docker.io/library/mediawiki
docker.io/library/memcached
docker.io/library/mongo
docker.io/library/mongo-express
docker.io/library/monica
docker.io/library/mono
docker.io/library/mysql
docker.io/library/nats
docker.io/library/nats-streaming
docker.io/library/neo4j
docker.io/library/neurodebian
docker.io/library/nextcloud
docker.io/library/nginx
docker.io/library/node
docker.io/library/notary
docker.io/library/odoo
docker.io/library/open-liberty
docker.io/library/openjdk
docker.io/library/oraclelinux
docker.io/library/orientdb
docker.io/library/owncloud
docker.io/library/percona
docker.io/library/perl
docker.io/library/photon
docker.io/library/php
docker.io/library/php-zendserver
docker.io/library/phpmyadmin
docker.io/library/plone
docker.io/library/postfixadmin
docker.io/library/postgres
docker.io/library/pypy
docker.io/library/python
docker.io/library/r-base
docker.io/library/rabbitmq
docker.io/library/rakudo-star
docker.io/library/redis
docker.io/library/redmine
docker.io/library/registry
docker.io/library/rethinkdb
docker.io/library/rocket.chat
docker.io/library/rockylinux
docker.io/library/ros
docker.io/library/ruby
docker.io/library/rust
docker.io/library/sapmachine
docker.io/library/satosa
docker.io/library/sentry
docker.io/library/silverpeas
docker.io/library/sl
docker.io/library/solr
docker.io/library/sonarqube
docker.io/library/spark
docker.io/library/spiped
docker.io/library/storm
docker.io/library/swift
docker.io/library/swipl
docker.io/library/teamspeak
docker.io/library/telegraf
docker.io/library/tomcat
docker.io/library/tomee
docker.io/library/traefik
docker.io/library/ubuntu
docker.io/library/unit
docker.io/library/varnish
docker.io/library/vault
docker.io/library/websphere-liberty
docker.io/library/wordpress
docker.io/library/xwiki
docker.io/library/yourls
docker.io/library/znc
docker.io/library/zookeeper
docker.io/libretranslate/libretranslate
docker.io/lihualiu/sam-6d
docker.io/linkease/ddnsto
docker.io/linkease/desktop-ubuntu-standard-amd64
docker.io/linkease/desktop-ubuntu-standard-arm64
docker.io/linkease/desktop-ubuntu2-standard-amd64
docker.io/linkease/desktop-ubuntu2-standard-arm64
docker.io/linkease/drawio-image-export
docker.io/linkease/drawio-plantuml-server
docker.io/linkease/istoreduprk35xx
docker.io/linkease/istoredupx86_64
docker.io/linkease/istorepanel
docker.io/linkease/kspeeder
docker.io/linkease/linkease
docker.io/linkease/open-webui
docker.io/linkease/pve
docker.io/linkease/runmynas
docker.io/linkease/webvirtcloud
docker.io/linuxserver/*
docker.io/linuxsuren/api-testing
docker.io/linuxsuren/atest-ext-store-orm
docker.io/livekit/*
docker.io/liwei2633/gopeed
docker.io/lizheming/waline
docker.io/lkw199711/smanga
docker.io/lldap/lldap
docker.io/lmcache/*
docker.io/lmsysorg/*
docker.io/lobehub/*
docker.io/localai/localai
docker.io/localstack/localstack
docker.io/loggieio/loggie
docker.io/longhornio/*
docker.io/louislam/*
docker.io/luojiecong/index-tts
docker.io/m1k1o/*
docker.io/mageai/mageai
docker.io/maildev/maildev
docker.io/mailserver/*
docker.io/manjarolinux/*
docker.io/manticoresearch/manticore
docker.io/maptiler/*
docker.io/martialblog/limesurvey
docker.io/mattermost/focalboard
docker.io/mattermost/mattermost-team-edition
docker.io/mauricenino/dashdot
docker.io/maxkeytop/*
docker.io/mayswind/ezbookkeeping
docker.io/mcp/*
docker.io/menci/archlinuxarm
docker.io/messense/cargo-zigbuild
docker.io/metabase/*
docker.io/metacontrollerio/metacontroller
docker.io/michaelf34/infinity
docker.io/mikefarah/yq
docker.io/milvusdb/*
docker.io/mindsdb/mindsdb
docker.io/mineru/sglang
docker.io/minio/*
docker.io/mintplexlabs/anythingllm
docker.io/mirantis/*
docker.io/mitmproxy/mitmproxy
docker.io/mlikiowa/napcat-docker
docker.io/mlocati/php-extension-installer
docker.io/mmcauliffe/montreal-forced-aligner
docker.io/moby/*
docker.io/mohsinonxrm/*
docker.io/mongodb/mongodb-community-server
docker.io/moonrailgun/tianji
docker.io/mpioperator/mpi-operator
docker.io/mplatform/manifest-tool
docker.io/mpromonet/webrtc-streamer
docker.io/mtphotos/mt-photos
docker.io/multiarch/*
docker.io/mwader/webdav
docker.io/myscale/myscaledb
docker.io/mysql/*
docker.io/n8nio/*
docker.io/nacos/*
docker.io/nastools/nas-tools
docker.io/natsio/*
docker.io/ncbi/pgap
docker.io/neilpang/acme.sh
docker.io/neosmemo/memos
docker.io/netbirdio/*
docker.io/netbox-community/netbox
docker.io/netdata/netdata
docker.io/networkstatic/iperf3
docker.io/neuvector/*
docker.io/newfuture/ddns
docker.io/newsnowlabs/dockside
docker.io/nextcloud/all-in-one
docker.io/nginx/*
docker.io/nginxinc/*
docker.io/nickfedor/watchtower
docker.io/nicolaka/netshoot
docker.io/nobodyiam/apollo-quick-start
docker.io/nocobase/nocobase
docker.io/nocodb/nocodb
docker.io/nodered/node-red
docker.io/nriver/trilium-cn
docker.io/nsqio/nsq
docker.io/nvidia/*
docker.io/nyanmisaka/jellyfin
docker.io/oamdev/*
docker.io/oblakstudio/redisinsight
docker.io/obsidiandynamics/kafdrop
docker.io/oceanbase/oceanbase-ce
docker.io/oceanbase/seekdb
docker.io/ogarcia/archlinux
docker.io/oguzpastirmaci/gpu-burn
docker.io/oliver006/*
docker.io/ollama/*
docker.io/onlyoffice/*
docker.io/openclaw/openclaw
docker.io/opencloudeu/opencloud-rolling
docker.io/opencoze/*
docker.io/openebs/*
docker.io/openeuler/*
docker.io/openfga/*
docker.io/opengeminidb/opengemini-server
docker.io/opengrok/docker
docker.io/openkruise/*
docker.io/openlistteam/openlist
docker.io/openmetadata/*
docker.io/openmined/syft-backend
docker.io/openmmlab/*
docker.io/openpolicyagent/gatekeeper
docker.io/openpolicyagent/opa
docker.io/openresty/openresty
docker.io/opensearchproject/*
docker.io/opensecurity/mobile-security-framework-mobsf
docker.io/openstitching/stitch
docker.io/opensuse/*
docker.io/openvino/*
docker.io/openvpn/openvpn-as
docker.io/openwhisk/*
docker.io/openzipkin/*
docker.io/osixia/*
docker.io/osrf/*
docker.io/ossrs/srs
docker.io/otel/*
docker.io/outlinesdev/outlines
docker.io/outlinewiki/outline
docker.io/oven/bun
docker.io/owncloud/server
docker.io/p3terx/aria2-pro
docker.io/p3terx/ariang
docker.io/paddlepaddle/paddle
docker.io/paketobuildpacks/*
docker.io/pandoc/*
docker.io/paradedb/*
docker.io/passbolt/passbolt
docker.io/penpotapp/*
docker.io/pepperlabs/peppermint
docker.io/percona/*
docker.io/pgautoupgrade/pgautoupgrade
docker.io/pgrouting/pgrouting
docker.io/pgvector/pgvector
docker.io/photoprism/photoprism
docker.io/phpmyadmin/*
docker.io/phpswoole/swoole
docker.io/pierky/bird
docker.io/pingcap/*
docker.io/plantuml/plantuml-server
docker.io/plexinc/pms-docker
docker.io/plugins/docker
docker.io/podwide/cosyvoice
docker.io/pointcloudlibrary/env
docker.io/polardbx/polardb-x
docker.io/portainer/*
docker.io/postgis/postgis
docker.io/postgrest/postgrest
docker.io/pragkent/alidns-webhook
docker.io/privoce/vocechat-server
docker.io/prodrigestivill/postgres-backup-local
docker.io/projectcontour/contour-authserver
docker.io/projecthami/*
docker.io/prom/*
docker.io/prometheuscommunity/*
docker.io/provectuslabs/kafka-ui
docker.io/proxysql/proxysql
docker.io/pymumu/smartdns
docker.io/pytorch/*
docker.io/qdrant/*
docker.io/qdtoday/qd
docker.io/qemux/qemu-docker
docker.io/qingpan/rnacos
docker.io/qmcgaw/ddns-updater
docker.io/questdb/questdb
docker.io/quickwit/*
docker.io/qwenllm/*
docker.io/rabbitmqoperator/cluster-operator
docker.io/radondb/*
docker.io/ramonvc/freegpt-webui
docker.io/rancher/*
docker.io/rayproject/*
docker.io/rclone/*
docker.io/reactivetechio/kubegres
docker.io/reallibrephotos/librephotos
docker.io/reallibrephotos/librephotos-frontend
docker.io/reallibrephotos/librephotos-proxy
docker.io/redash/*
docker.io/redhat/*
docker.io/redis/*
docker.io/redislabs/*
docker.io/rednotehilab/dots.ocr
docker.io/redpandadata/console
docker.io/redpandadata/kminion
docker.io/redroid/redroid
docker.io/reportportal/reportportal
docker.io/resmoio/kubernetes-event-exporter
docker.io/restatedev/restate
docker.io/ribbybibby/ssl-exporter
docker.io/riscv64/*
docker.io/rockylinux/rockylinux
docker.io/rocm/*
docker.io/rolebasedgroup/rbgs-controller
docker.io/romancin/tinymediamanager
docker.io/rommapp/romm
docker.io/rook/ceph
docker.io/rsyslog/*
docker.io/rucio/*
docker.io/rustdesk/rustdesk-server
docker.io/rustdesk/rustdesk-server-pro
docker.io/rustdesk/rustdesk-server-s6
docker.io/rustfs/rustfs
docker.io/rustlang/rust
docker.io/rzuo/pose
docker.io/sameersbn/**
docker.io/savatar101/omniparse
docker.io/schemahero/*
docker.io/schnell18/rocketmq-dashboard
docker.io/seafileltd/seafile-mc
docker.io/searxng/searxng
docker.io/seataio/*
docker.io/secoresearch/rsync
docker.io/selectdb/*
docker.io/selenium/*
docker.io/semgrep/*
docker.io/semitechnologies/*
docker.io/senthilrch/*
docker.io/serengil/deepface
docker.io/serversideup/*
docker.io/shieldsio/shields
docker.io/shingarey/foundationpose_custom_cuda121
docker.io/sickcodes/docker-osx
docker.io/silkeh/clang
docker.io/simonrupf/chronyd
docker.io/sinamics/ztnet
docker.io/sissbruecker/linkding
docker.io/sj26/mailcatcher
docker.io/slimerl/slime
docker.io/slskd/slskd
docker.io/snipe/snipe-it
docker.io/snowdreamtech/frpc
docker.io/snowdreamtech/frps
docker.io/solace/solace-pubsub-standard
docker.io/solidnerd/bookstack
docker.io/sonatype/*
docker.io/sonicorg/sonic-client-web-base
docker.io/sonobuoy/*
docker.io/soulter/astrbot
docker.io/sourcegraph/*
docker.io/squidfunk/*
docker.io/starrocks/*
docker.io/steamcmd/*
docker.io/stilleshan/frpc
docker.io/stilleshan/frps
docker.io/stirlingtools/stirling-pdf
docker.io/stnsmith/fossflow
docker.io/streamnative/*
docker.io/styletang/rocketmq-console-ng
docker.io/subfuzion/netcat
docker.io/suisuijiang/fiora
docker.io/sulinggg/openwrt
docker.io/supabase/*
docker.io/superbench/superbench
docker.io/supermanito/arcadia
docker.io/superng6/aria2
docker.io/superng6/qbittorrentee
docker.io/svhd/logto
docker.io/swaggerapi/*
docker.io/syncthing/syncthing
docker.io/tabbyml/tabby
docker.io/tailscale/*
docker.io/taksss/php-epg
docker.io/talebook/talebook
docker.io/talkincode/toughradius
docker.io/tarscloud/framework
docker.io/tdengine/*
docker.io/techblog/broadlinkmanager
docker.io/technitium/dns-server
docker.io/temporalio/*
docker.io/tensorchord/pgvecto-rs
docker.io/tensorflow/*
docker.io/tensorfusion/*
docker.io/teslamate/*
docker.io/testcontainers/*
docker.io/texlive/texlive
docker.io/thanosio/*
docker.io/thingsboard/tb-node
docker.io/thingsboard/tb-postgres
docker.io/thomassong/gpu-admission
docker.io/tiangolo/*
docker.io/tianon/postgres-upgrade
docker.io/timberio/*
docker.io/timescale/timescaledb
docker.io/timonwong/prometheus-webhook-dingtalk
docker.io/timothyjmiller/cloudflare-ddns
docker.io/tinygo/tinygo
docker.io/tinymediamanager/tinymediamanager
docker.io/tnir/mysqlclient
docker.io/tomkellygenetics/universc
docker.io/tonistiigi/binfmt
docker.io/tonistiigi/xx
docker.io/traefik/whoami
docker.io/trafficserver/trafficserver
docker.io/treeverse/lakefs
docker.io/triliumnext/notes
docker.io/trinodb/trino
docker.io/trustpilot/beat-exporter
docker.io/tryretool/backend
docker.io/tugraph/*
docker.io/tunathu/bandersnatch
docker.io/tusproject/tusd
docker.io/tutelgroup/*
docker.io/twinproduction/gatus
docker.io/ubuntu/*
docker.io/ultralytics/*
docker.io/unclecode/crawl4ai
docker.io/unityci/editor
docker.io/uozi/nginx-ui
docker.io/vaalacat/frp-panel
docker.io/valkey/valkey
docker.io/vaultwarden/server
docker.io/vdsm/virtual-dsm
docker.io/velero/*
docker.io/verdaccio/*
docker.io/verlai/*
docker.io/vesoft/*
docker.io/victoriametrics/*
docker.io/viktorstrate/*
docker.io/vllm/*
docker.io/volcanosh/*
docker.io/vulhub/kkfileview
docker.io/wallabag/wallabag
docker.io/wandb/*
docker.io/weaveworks/*
docker.io/webdevops/*
docker.io/wechatopenai/*
docker.io/wekanteam/wekan
docker.io/whyour/qinglong
docker.io/willfarrell/autoheal
docker.io/wiremock/wiremock
docker.io/wiznote/wizserver
docker.io/woodpeckerci/*
docker.io/wurstmeister/kafka
docker.io/wurstmeister/zookeeper
docker.io/xhofe/alist
docker.io/xhongc/music_tag_web
docker.io/xiaojusurvey/xiaoju-survey
docker.io/xiaoyaliu/alist
docker.io/xixihahaliu01/qanything-linux
docker.io/xixihahaliu01/qanything-mac
docker.io/xixihahaliu01/qanything-win
docker.io/xprobe/xinference
docker.io/xukuanhit/air_slam
docker.io/xuxueli/xxl-job-admin
docker.io/yandex/clickhouse-server
docker.io/ydlhero/chatgpt-web-midjourney-proxy
docker.io/yedf/dtm
docker.io/yidadaa/chatgpt-next-web
docker.io/ypptec/nascab
docker.io/zabbix/*
docker.io/zadam/trilium
docker.io/zendesk/maxwell
docker.io/zerotier/*
docker.io/zhaojun1998/zfile-pro
docker.io/zhayujie/chatgpt-on-wechat
docker.io/zilliz/*
docker.io/zlijingtao/neurobfuscator
docker.io/zlmediakit/zlmediakit
docker.io/zmisgod/iptvchecker
docker.io/zmister/mrdoc
docker.io/zulip/docker-zulip
docker.osgeo.org/**
docker.stirlingpdf.com/stirlingtools/stirling-pdf
gcr.io/**
ghcr.io/666ghj/bettafish
ghcr.io/9001/copyparty-ac
ghcr.io/aas-ee/open-web-search
ghcr.io/actions/**
ghcr.io/advplyr/audiobookshelf
ghcr.io/ajnart/homarr
ghcr.io/amamba-io/**
ghcr.io/analogj/scrutiny
ghcr.io/anduin2017/how-to-cook
ghcr.io/anomalyco/opencode
ghcr.io/apache/**
ghcr.io/apple/**
ghcr.io/aquasecurity/**
ghcr.io/armbian/**
ghcr.io/astral-sh/**
ghcr.io/authzed/spicedb
ghcr.io/authzed/spicedb-operator
ghcr.io/autowarefoundation/autoware
ghcr.io/baizeai/**
ghcr.io/benc-uk/kubeview
ghcr.io/berriai/litellm
ghcr.io/bigcode-project/evaluation-harness
ghcr.io/bigcode-project/evaluation-harness-multiple
ghcr.io/biliup/caution
ghcr.io/binary-husky/gpt_academic_with_latex
ghcr.io/blakeblackshear/**
ghcr.io/brenner-tobias/cloudflared/*
ghcr.io/canner/*
ghcr.io/chaos-mesh/**
ghcr.io/chaosblade-io/**
ghcr.io/chroma-core/chroma
ghcr.io/cinnamon/kotaemon
ghcr.io/cirruslabs/**
ghcr.io/cloudtty/cloudshell
ghcr.io/coder/**
ghcr.io/codex-team/codex.docs
ghcr.io/containerd/**
ghcr.io/coollabsio/coolify-helper
ghcr.io/coqui-ai/tts
ghcr.io/corentinth/it-tools
ghcr.io/cowboysysop/pytest
ghcr.io/crazy-max/fail2ban
ghcr.io/cross-rs/**
ghcr.io/danny-avila/librechat-dev
ghcr.io/daocloud/**
ghcr.io/dbt-labs/dbt-core
ghcr.io/decohererk/decotv
ghcr.io/deepflowio/rust-build
ghcr.io/dexidp/**
ghcr.io/docling-project/*
ghcr.io/dtzar/**
ghcr.io/easytier/easytier
ghcr.io/elastic/opentelemetry-demo
ghcr.io/elf-io/*
ghcr.io/esphome/esphome
ghcr.io/estrellaxd/auto_bangumi
ghcr.io/eunomia-bpf/libbpf-template
ghcr.io/fatedier/frpc
ghcr.io/fief-dev/fief
ghcr.io/fish2018/pansou-web
ghcr.io/fission/**
ghcr.io/flannel-io/*
ghcr.io/flexget/flexget
ghcr.io/fluent/fluent-operator/*
ghcr.io/freecodecamp/devdocs
ghcr.io/gethomepage/homepage
ghcr.io/getsentry/*
ghcr.io/ggerganov/llama.cpp
ghcr.io/ggml-org/llama.cpp
ghcr.io/gnzsnz/ib-gateway
ghcr.io/go-rod/rod
ghcr.io/goauthentik/**
ghcr.io/gohugoio/hugo
ghcr.io/google/**
ghcr.io/graalvm/*
ghcr.io/grafana-operator/*
ghcr.io/grafana/*
ghcr.io/hassio-addons/**
ghcr.io/headlamp-k8s/headlamp
ghcr.io/helm/**
ghcr.io/hkuds/lightrag
ghcr.io/homarr-labs/homarr
ghcr.io/home-assistant/**
ghcr.io/home-operations/*
ghcr.io/huaweiclouddeveloper/**
ghcr.io/huggingface/*
ghcr.io/hwameistor/**
ghcr.io/imagegenius/immich
ghcr.io/immich-app/**
ghcr.io/imputnet/cobalt
ghcr.io/infrastructure-io/**
ghcr.io/inspektor-gadget/gadget/*
ghcr.io/jd-opensource/**
ghcr.io/jimmidyson/configmap-reload
ghcr.io/joeferner/redis-commander
ghcr.io/joernio/joern
ghcr.io/k3d-io/**
ghcr.io/k3s-io/**
ghcr.io/k8snetworkplumbingwg/**
ghcr.io/karakeep-app/karakeep
ghcr.io/kdoctor-io/**
ghcr.io/kedacore/*
ghcr.io/khoj-ai/**
ghcr.io/klts-io/**
ghcr.io/komari-monitor/komari
ghcr.io/koodo-reader/koodo-reader
ghcr.io/koordinator-sh/**
ghcr.io/ksmartdata/**
ghcr.io/kube-vip/**
ghcr.io/kubean-io/**
ghcr.io/kubeflow/**
ghcr.io/kyverno/**
ghcr.io/labring/calico
ghcr.io/labring/fastgpt
ghcr.io/labring/fastgpt-sandbox
ghcr.io/labring/lvscare
ghcr.io/lemker/unifi-os-server
ghcr.io/librespeed/speedtest
ghcr.io/linuxsuren/api-testing
ghcr.io/linuxsuren/atest-ext-store-orm
ghcr.io/llm-d/**
ghcr.io/logseq/logseq-webapp
ghcr.io/lunatechlab/moontv
ghcr.io/luskits/**
ghcr.io/macbre/nginx-http3
ghcr.io/mastodon/mastodon
ghcr.io/maybe-finance/**
ghcr.io/megacloudcontainer/**
ghcr.io/mellanox/**
ghcr.io/mendableai/firecrawl
ghcr.io/metalbear-co/**
ghcr.io/metatool-ai/metamcp
ghcr.io/metatube-community/metatube-server
ghcr.io/microsoft/**
ghcr.io/mlflow/*
ghcr.io/modelcontextprotocol/inspector
ghcr.io/mosn/**
ghcr.io/mostlygeek/llama-swap
ghcr.io/music-assistant/server
ghcr.io/nicholas-fedor/watchtower
ghcr.io/nvidia/**
ghcr.io/open-telemetry/**
ghcr.io/open-webui/open-webui
ghcr.io/open-webui/pipelines
ghcr.io/opencidn/**
ghcr.io/openclaw/openclaw
ghcr.io/openfaas/**
ghcr.io/openinsight-proj/**
ghcr.io/openlistteam/openlist-git
ghcr.io/ot-container-kit/**
ghcr.io/parkervcp/yolks
ghcr.io/phioranex/openclaw-docker
ghcr.io/plankanban/planka
ghcr.io/project-zot/**
ghcr.io/projectcontour/**
ghcr.io/ptbsare/home-assistant-addons/aarch64-addon-sherpa-onnx-tts-stt
ghcr.io/puppeteer/puppeteer
ghcr.io/rails/**
ghcr.io/rancher/**
ghcr.io/rjmalagon/ollama-linux-amd-apu
ghcr.io/seriousm4x/upsnap
ghcr.io/siderolabs/*
ghcr.io/siemens/**
ghcr.io/sillytavern/sillytavern
ghcr.io/songquanpeng/one-api
ghcr.io/speaches-ai/speaches
ghcr.io/spidernet-io/**
ghcr.io/spiffe/**
ghcr.io/spring-ai-alibaba/lynxe
ghcr.io/sugarforever/peanut-shell
ghcr.io/sumologic/**
ghcr.io/suwayomi/suwayomi-server
ghcr.io/suwayomi/tachidesk
ghcr.io/systemed/tilemaker
ghcr.io/szemeng76/lunatv
ghcr.io/tangly1024/notionnext
ghcr.io/timeplus-io/**
ghcr.io/tiryoh/ros2-desktop-vnc
ghcr.io/toeverything/affine-graphql
ghcr.io/umami-software/umami
ghcr.io/universaloj/**
ghcr.io/vllm-project/guidellm
ghcr.io/wg-easy/wg-easy
ghcr.io/wzshiming/**
ghcr.io/ylianst/meshcentral
ghcr.io/zalando/**
ghcr.io/zammad/zammad
ghcr.io/zitadel/**
k8s.gcr.io/**
lscr.io/linuxserver/**
mcr.microsoft.com/**
nvcr.io/**
ollama.ai/**
public.ecr.aws/amazonlinux/**
public.ecr.aws/appmesh/**
public.ecr.aws/bitnami/*
public.ecr.aws/cloudwatch-agent/**
public.ecr.aws/datadog/**
public.ecr.aws/docker/**
public.ecr.aws/dynatrace/**
public.ecr.aws/eks-distro/**
public.ecr.aws/karpenter/**
public.ecr.aws/lambda/**
public.ecr.aws/mackerel/**
public.ecr.aws/mountpoint-s3-csi-driver/**
public.ecr.aws/nginx/**
public.ecr.aws/ubuntu/**
quay.io/aipipeline/*
quay.io/argoproj/*
quay.io/argoprojlabs/*
quay.io/ascend/*
quay.io/brancz/*
quay.io/calico/*
quay.io/ceph/ceph
quay.io/ceph/cosi
quay.io/cephcsi/cephcsi
quay.io/cilium/*
quay.io/coreos/*
quay.io/csiaddons/k8s-sidecar
quay.io/external_storage/*
quay.io/frrouting/frr
quay.io/go-skynet/local-ai
quay.io/goswagger/*
quay.io/grafana-operator/*
quay.io/ibm-spectrum-scale/*
quay.io/jaegertracing/*
quay.io/jetstack/*
quay.io/jetstack/charts/*
quay.io/jupyter/*
quay.io/jupyterhub/*
quay.io/k0sproject/*
quay.io/k8scsi/*
quay.io/kata-containers/*
quay.io/keycloak/keycloak
quay.io/kiali/*
quay.io/kiwigrid/*
quay.io/kuberay/*
quay.io/kubernetes-ingress-controller/*
quay.io/kubernetes-sigs/*
quay.io/kubespray/*
quay.io/kubevirt/*
quay.io/libpod/skopeo_cidev
quay.io/metallb/*
quay.io/minio/*
quay.io/mongodb/*
quay.io/nmstate/*
quay.io/nuclio/*
quay.io/operator-framework/*
quay.io/operatorhubio/minio-operator
quay.io/opstree/*
quay.io/podman/stable
quay.io/prometheus-operator/*
quay.io/prometheus/*
quay.io/prometheuscommunity/*
quay.io/quarkus/*
quay.io/redhat-developer/*
quay.io/sameersbn/squid
quay.io/skopeo/*
quay.io/spotahome/*
quay.io/strimzi/*
quay.io/submariner/*
quay.io/tigera/*
registry.developers.crunchydata.com/crunchydata/pgo-deployer
registry.gitlab.com/gitlab-org/**
registry.gitlab.com/purelb/purelb/purelb
registry.heroiclabs.com/heroiclabs/nakama
registry.jujucharms.com/**
registry.k8s.io/**
registry.opensource.zalan.do/**
registry.rocket.chat/**
rocks.canonical.com/**
us-central1-docker.pkg.dev/k8s-staging-images/**
us-central1-docker.pkg.dev/keephq/keep/keep-api
us-central1-docker.pkg.dev/keephq/keep/keep-ui
us.gcr.io/k8s-artifacts-prod/**


================================================
FILE: docs/local-cache/README.md
================================================
# 部署内网缓存

## 简介

本地缓存部署用于在内网环境中加速镜像拉取,减少对外网的依赖。通过设置一个本地镜像仓库,您可以缓存常用的镜像。

## 部署步骤

1. **准备环境**  

确保已安装 Docker 和 Docker Compose。

2. **配置 Docker Compose 文件**  

创建一个 `docker-compose.yml` 文件:

```yaml
services:
  registry:
    image: m.daocloud.io/docker.io/library/registry:3
    restart: unless-stopped
    ports:
    - 8888:8888
    command:
    - /etc/docker/registry/config.yml
    volumes:
    - cache-data:/var/lib/registry
    configs:
    - source: registry-config
      target: /etc/docker/registry/config.yml
configs:
  registry-config:
    content: |
      version: 0.1
      storage:
        delete:
          enabled: true
        filesystem:
          rootdirectory: /var/lib/registry
      http:
        addr: :8888
      proxy:
        remoteurl: https://m.daocloud.io
        ttl: 2160h
volumes:
  cache-data: {}
```

4. **启动服务**  
```bash
docker compose up -d
```

5. **配置 Docker 客户端**  
在 `/etc/docker/daemon.json` 中添加以下内容:
```json
{
  "insecure-registries": ["<your-registry-ip>:<your-registry-port>"]
}

```
然后重启 Docker 服务:
```bash
systemctl restart docker
```

## 用法

现在您的 `<your-registry-ip>:<your-registry-port>/` 已经是 `m.daocloud.io/` 的本地缓存代理

后续就像 `m.daocloud.io` 加前缀一样, 只需要在原始镜像地址前加上 `<your-registry-ip>:<your-registry-port>/` 即可。

例如,拉取 `docker.io/library/nginx:latest` 镜像,可以使用以下命令:
```bash
docker pull <your-registry-ip>:<your-registry-port>/docker.io/library/nginx:latest
```



================================================
FILE: hack/badge.sh
================================================
#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail

QUICKLY="${QUICKLY:-}"
cat *"_sync.log" > "sync.log"
sync="$(cat "sync.log" | grep " SYNCHRONIZED: " | wc -l | tr -d ' ' || :)"
unsync="$(cat "sync.log" | grep " NOT-SYNCHRONIZED: " | wc -l | tr -d ' ' || :)"
sum=$(($sync + $unsync))

if [[ "${sum}" -eq 0 ]]; then
    echo "No sync"
    exit 1    
fi

if [[ "${QUICKLY}" == "true" ]]; then
    echo "https://img.shields.io/badge/Sync-${sync}%2F${sum}-blue"
    wget "https://img.shields.io/badge/Sync-${sync}%2F${sum}-blue" -O badge.svg
else
    echo "https://img.shields.io/badge/Deep%20Sync-${sync}%2F${sum}-blue"
    wget "https://img.shields.io/badge/Deep%20Sync-${sync}%2F${sum}-blue" -O badge.svg
fi


================================================
FILE: hack/correct-image.sh
================================================
#!/usr/bin/env bash

function guess_image() {
    local image="${1}"

    image="${image// /}"
    image="${image#\/}"
    image="${image%\/}"

    if [[ -z "${image}" ]]; then
        return
    fi

    if [[ "${image}" == *"registry.hub.docker.com/r/"* ]]; then
        image="docker.io/${image##*registry.hub.docker.com\/r\/}"
    fi
    if [[ "${image}" == *"hub.docker.com/r/"* ]]; then
        image="docker.io/${image##*hub.docker.com\/r\/}"
    fi
    if [[ "${image}" != *"/"* ]]; then
        image="library/${image}"
    fi
    if [[ "${image%%/*}" != *"."* ]]; then
        image="docker.io/${image}"
    fi
    if [[ "${image}" != *":"* ]]; then
        image="${image}:latest"
    fi
    if [[ "${image}" == *"//"* ]] || [[ "${image}" == *" "* ]]; then
        return
    fi

    echo "${image}"
}

guess_image "${1}"


================================================
FILE: hack/diff-image.sh
================================================
#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail

# Output more information that is out of synchronize
DEBUG="${DEBUG:-}"

IMAGE1="${1:-}"
IMAGE2="${2:-}"

SKOPEO="${SKOPEO:-skopeo}"
JQ="${JQ:-jq}"

# Allow image2 to have more tags than image1
INCREMENTAL="${INCREMENTAL:-}"

# Compare only tags that are in both images
QUICKLY="${QUICKLY:-}"

# If set, will compare the image tag patterns
QUICKLY_PATTERN="${QUICKLY_PATTERN:-}"

# Regexp that matches the tags
FOCUS="${FOCUS:-}"

# Regexp that matches the tags that needs to be skipped
SKIP="${SKIP:-}"

# Compare the number of tags in parallel
PARALLET="${PARALLET:-0}"

# Synchronize images from source to destination
SYNC="${SYNC:-}"

# Retry times
RETRY="${RETRY:-5}"

SELF="$(basename "${BASH_SOURCE[0]}")"

if [[ "${DEBUG}" == "true" ]]; then
    echo "DEBUG:           ${DEBUG}"
    echo "IMAGE1:          ${IMAGE1}"
    echo "IMAGE2:          ${IMAGE2}"
    echo "SKOPEO:          ${SKOPEO}"
    echo "JQ:              ${JQ}"
    echo "INCREMENTAL:     ${INCREMENTAL}"
    echo "QUICKLY:         ${QUICKLY}"
    echo "QUICKLY_PATTERN: ${QUICKLY_PATTERN}"
    echo "FOCUS:           ${FOCUS}"
    echo "SKIP:            ${SKIP}"
    echo "PARALLET:        ${PARALLET}"
    echo "SYNC:            ${SYNC}"
    echo "RETRY:           ${RETRY}"
fi

function check() {
    local image1="${1:-}"
    local image2="${2:-}"

    if [[ "${image1}" == "" ]] || [[ "${image2}" == "" ]]; then
        echo "Compares whether the synchronization of the two images is exactly the same"
        echo "Need to install jq and skopeo"
        echo "Usage:"
        echo " ${SELF}: <image1> <image2>"
        echo " ${SELF}: <image1:tag> <image2:tag>"
        echo "Env:"
        echo " DEBUG=true                # Output more information that is out of synchronize"
        echo " INCREMENTAL=true          # Allow image2 to have more tags than image1"
        echo " QUICKLY=true              # Compare only tags that are in both images"
        echo " QUICKLY_PATTERN=<pattern> # Regexp that matches the tags"
        echo " FOCUS=<pattern>           # Regexp that matches the tags"
        echo " SKIP=<pattern>            # Regexp that matches the tags that needs to be skipped"
        echo " PARALLET=<size>           # Compare the number of tags in parallel"
        echo " SYNC=true                 # Synchronize images from source to destination"
        echo " RETRY=<times>             # Retry times"
        return 2
    fi

    if [[ "${image1#*/}" =~ ":" ]]; then
        if [[ "${image2#*/}" =~ ":" ]]; then
            return 0
        else
            echo "${SELF}: ERROR: ${image1} and ${image2} must both be full images or not be tag references" >&2
            return 2
        fi
    else
        if [[ "${image2#*/}" =~ ":" ]]; then
            echo "${SELF}: ERROR: ${image1} and ${image2} must both be full images or not be tag references" >&2
            return 2
        else
            return 0
        fi
    fi
}

emptyLayer="sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"

function inspect() {
    local image="${1:-}"
    local raw=$(${SKOPEO} inspect --retry-times "${RETRY}" --raw --tls-verify=false "docker://${image}")
    if [[ "${raw}" == "" ]]; then
        echo "skopeo inspect --retry-times "${RETRY}" --raw --tls-verify=false docker://${image}" >&2
        echo "ERROR: Failed to inspect ${image}" >&2
        return 1
    fi

    local schemaVersion=$(echo "${raw}" | ${JQ} -r '.schemaVersion')
    case "${schemaVersion}" in
    1)
        echo "${raw}" | ${JQ} -r '.fsLayers[].blobSum' | grep -v "${emptyLayer}" | tac
        ;;
    2)
        local mediaType=$(echo "${raw}" | ${JQ} -r '.mediaType // "" ')
        if [[ "${mediaType}" == "" ]]; then
            if [[ "$(echo "${raw}" | ${JQ} -r '.layers | length')" -gt 0 ]]; then
                mediaType="layers"
            elif [[ "$(echo "${raw}" | ${JQ} -r '.manifests | length')" -gt 0 ]]; then
                mediaType="manifests"
            fi
        fi

        case "${mediaType}" in
        "layers" | "application/vnd.docker.distribution.manifest.v2+json")
            echo "${raw}" | ${JQ} -r '.layers[].digest' | grep -v "${emptyLayer}"
            ;;
        "manifests" | "application/vnd.docker.distribution.manifest.list.v2+json")
            local line=$(echo "${raw}" | ${JQ} -j '.manifests[] | .platform.architecture , " " , .platform.os , "\n"' | sort)
            IFS=$'\n'
            for args in ${line}; do
                local arch="${args%% *}"
                local os="${args##* }"
                echo ${args}
                ${SKOPEO} --override-arch "${arch}" --override-os "${os}" inspect --retry-times "${RETRY}" --config --tls-verify=false "docker://${image}" | jq -r '.rootfs.diff_ids[]'
            done
            unset IFS
            ;;
        *)
            echo "skopeo inspect --retry-times "${RETRY}" --raw --tls-verify=false docker://${image}" >&2
            if [[ "${DEBUG}" == "true" ]]; then
                echo "${raw}" >&2
            fi
            echo "${SELF}: ERROR: Unknown media type: ${mediaType}" >&2
            return 2
            ;;
        esac
        ;;
    *)
        echo "skopeo inspect --retry-times "${RETRY}" --raw --tls-verify=false docker://${image}" >&2
        if [[ "${DEBUG}" == "true" ]]; then
            echo "${raw}" >&2
        fi
        echo "${SELF}: ERROR: Unknown schema version: ${schemaVersion}" >&2
        return 2
        ;;
    esac
}

function copy-image() {
    local image1="${1:-}"
    local image2="${2:-}"

    ${SKOPEO} copy --retry-times "${RETRY}" --all --dest-tls-verify=false "docker://${image1}" "docker://${image2}"
}

function list-tags() {
    local image="${1:-}"
    local raw="$(${SKOPEO} list-tags --retry-times "${RETRY}" --tls-verify=false "docker://${image}" | ${JQ} -r '.Tags[]')"

    # Sort by string length
    raw=$(echo "${raw}" | awk '{print length, $0}' | sort -n | awk '{print $2}')

    if [[ "${FOCUS}" != "" ]]; then
        local skip=$(echo "${raw}" | grep -v -E "${FOCUS}")
        if [[ "${skip}" != "" ]]; then
            echo "${SELF}: SKIP: ${image} with focus: ${FOCUS}:" ${skip} >&2
        fi
        raw="$(echo "${raw}" | grep -E "${FOCUS}" || :)"
    fi

    if [[ "${SKIP}" != "" ]]; then
        local skip=$(echo "${raw}" | grep -E "${SKIP}")
        if [[ "${skip}" != "" ]]; then
            echo "${SELF}: SKIP: ${image} with skip: ${SKIP}:" ${skip} >&2
        fi
        raw="$(echo "${raw}" | grep -v -E "${SKIP}" || :)"
    fi
    echo "${raw}"
}

function diff-image-with-tag() {
    local image1="${1:-}"
    local image2="${2:-}"

    if [[ "${QUICKLY}" == "true" ]]; then
        local tag1="${image1##*:}"
        local tag2="${image2##*:}"
        if [[ "${tag1}" != "${tag2}" ]]; then
            echo "${SELF}: NOT-SYNCHRONIZED: ${image1} and ${image2} are not in synchronized" >&2
            return 1
        fi
         
        if [[ "${QUICKLY_PATTERN}" == "" || ("${QUICKLY_PATTERN}" != "" && "${tag1}" =~ ${QUICKLY_PATTERN}) ]]; then
            echo "${SELF}: SYNCHRONIZED: ${image1} and ${image2} are in synchronized" >&2
            return 0
        fi
    fi

    local inspect2="$(inspect ${image2})"
    if [[ "${inspect2}" == "" ]]; then
        echo "${SELF}: NOT-SYNCHRONIZED: ${image1} and ${image2} are not in synchronized, ${image2} content is empty" >&2
        return 1
    fi

    local inspect1="$(inspect ${image1})"
    local diff_raw=$(diff --unified <(echo "${inspect1}") <(echo "${inspect2}"))

    if [[ "${diff_raw}" != "" ]]; then
        echo "${SELF}: NOT-SYNCHRONIZED: ${image1} and ${image2} are not in synchronized" >&2
        if [[ "${DEBUG}" == "true" ]]; then
            echo "DEBUG: image1 ${image1}:" >&2
            echo "${inspect1}" >&2
            echo "DEBUG: image2 ${image2}:" >&2
            echo "${inspect2}" >&2
            echo "diff:" >&2
            echo "${diff_raw}" >&2
        fi
        return 1
    fi
    echo "${SELF}: SYNCHRONIZED: ${image1} and ${image2} are in synchronized" >&2
}

function diff-image() {
    local image1="${1:-}"
    local image2="${2:-}"

    local tags1="$(list-tags ${image1})"
    local tags2="$(list-tags ${image2})"
    local diff_raw="$(diff --unified <(echo "${tags1}") <(echo "${tags2}") | grep -v -E '^---' | grep -v -E '^\+\+\+' || :)"
    local increase="$(echo "${diff_raw}" | grep -E '^\+' | sed 's/^\+//' || :)"
    local reduce="$(echo "${diff_raw}" | grep -E '^-' | sed 's/^-//' || :)"
    local common="${tags1}"

    if [[ "${increase}" != "" ]]; then
        common="$(echo "${common}" | grep -v -f <(echo "${increase}") || :)"
    fi

    if [[ "${reduce}" != "" ]]; then
        common="$(echo "${common}" | grep -v -f <(echo "${reduce}") || :)"
    fi

    if [[ "${INCREMENTAL}" == "true" ]]; then
        increase=""
    fi

    if [[ "${QUICKLY}" == "" ]] || [[ "${reduce}" != "" ]] || [[ "${increase}" != "" ]]; then
        echo "${SELF}: NOT-SYNCHRONIZED-TAGS: ${image1} and ${image2} are not in synchronized" >&2
        if [[ "${DEBUG}" == "true" ]]; then
            echo "DEBUG: image1 ${image1}:" >&2
            echo "${tags1}" >&2
            echo "DEBUG: image2 ${image2}:" >&2
            echo "${tags2}" >&2
            echo "DEBUG: diff:" >&2
            echo "${diff_raw}" >&2
        fi
        for tag in ${reduce}; do
            echo "${SELF}: NOT-SYNCHRONIZED: ${image1}:${tag} and ${image2}:${tag} are not in synchronized, ${image2}:${tag} does not exist" >&2
            if [[ "${SYNC}" == "true" ]]; then
                echo "${SELF}: SYNCHRONIZE: synchronize from ${image1}:${tag} to ${image2}:${tag}" >&2
                copy-image "${image1}:${tag}" "${image2}:${tag}" >&2
            fi
        done
        for tag in ${increase}; do
            echo "${SELF}: NOT-SYNCHRONIZED: ${image1}:${tag} and ${image2}:${tag} are not in synchronized, ${image1}:${tag} does not exist" >&2
        done
        echo "${common}"
        return 1
    fi
    echo "${SELF}: SYNCHRONIZED-TAGS: ${image1} and ${image2} are in synchronized" >&2
    echo "${common}"
    return 0
}

function wait_jobs() {
    local job_num=${1:-3}
    local perc=$(jobs -p | wc -l)
    while [ "${perc}" -gt "${job_num}" ]; do
        sleep 1
        perc=$(jobs -p | wc -l)
    done
}

function main() {
    local image1="${1:-}"
    local image2="${2:-}"

    if [[ "${image1#*/}" =~ ":" ]]; then
        if [[ "${SYNC}" == "true" ]]; then
            echo "${SELF}: SYNCHRONIZE: synchronize from ${image1} to ${image2}" >&2
            copy-image "${image1}" "${image2}"
            return $?
        fi
        diff-image-with-tag "${image1}" "${image2}" >/dev/null
        return $?
    fi

    local list=$(diff-image "${image1}" "${image2}")

    local notsynced=()
    if [[ "${PARALLET}" -eq 0 ]]; then
        for tag in ${list}; do
            diff-image-with-tag "${image1}:${tag}" "${image2}:${tag}" >/dev/null || {
                if [[ "${SYNC}" == "true" ]]; then
                    echo "${SELF}: SYNCHRONIZE: synchronize from ${image1}:${tag} to ${image2}:${tag}" >&2
                    copy-image "${image1}:${tag}" "${image2}:${tag}"
                fi
                notsynced+=("${tag}")
            }
        done
    else
        for tag in ${list}; do
            wait_jobs "${PARALLET}"
            diff-image-with-tag "${image1}:${tag}" "${image2}:${tag}" >/dev/null || {
                if [[ "${SYNC}" == "true" ]]; then
                    echo "${SELF}: SYNCHRONIZE: synchronize from ${image1}:${tag} to ${image2}:${tag}" >&2
                    copy-image "${image1}:${tag}" "${image2}:${tag}"
                fi
                notsynced+=("${tag}")
            } &
        done
        wait
    fi

    if [[ "${#notsynced[@]}" -gt 0 ]]; then
        echo "${SELF}: INFO: ${image1} and ${image2} are not in synchronized, there are not synchronized tags ${#notsynced[@]}: ${notsynced[*]}" >&2
        return 1
    fi
}

check "${IMAGE1}" "${IMAGE2}"
main "${IMAGE1}" "${IMAGE2}"


================================================
FILE: hack/diff.sh
================================================
#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail

source "$(dirname "${BASH_SOURCE}")/helper.sh"
cd "${ROOT}"

DEBUG="${DEBUG:-}"
INCREMENTAL="${INCREMENTAL:-}"
QUICKLY="${QUICKLY:-}"
SYNC="${SYNC:-}"
PARALLET="${PARALLET:-0}"
PARALLET_JOBS="${PARALLET_JOBS:-4}"
EXCLUDE="$(helper::exclude)"

declare -A DOMAIN_MAP=()

function wait_jobs() {
    local job_num=${1:-3}
    local perc=$(jobs -p | wc -l)
    while [ "${perc}" -gt "${job_num}" ]; do
        sleep 1
        perc=$(jobs -p | wc -l)
    done
}

function sync_with_domain() {
    local domain="${1}"

    local list=$(echo ${DOMAIN_MAP[${domain}]} | tr ' ' '\n' | shuf)
    for image in ${list}; do
        regex="${DEFAULT_REGEX}"
        if [[ "${image#*/}" =~ ":" ]]; then
            regex="${image##*:}"
            image="${image%:*}"
        fi
        local to="$(helper::replace_domain "${domain}/${image}")"

        local logfile="${to//\//_}_sync.log"
        echo >"${logfile}"

        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}" || {
            echo "Error: diff image ${domain}/${image} $(helper::replace_domain "${domain}/${image}")"
        }
    done
}

function main() {

    for image in $(helper::get_source); do
        key="${image%%/*}"
        val="${image#*/}"
        if [[ -v "DOMAIN_MAP[${key}]" ]]; then
            DOMAIN_MAP["${key}"]+=" ${val}"
        else
            DOMAIN_MAP["${key}"]="${val}"
        fi
    done

    for domain in "${!DOMAIN_MAP[@]}"; do
        if [[ "${PARALLET_JOBS}" -eq 0 ]]; then
            sync_with_domain "${domain}"
        else
            wait_jobs "${PARALLET_JOBS}"
            sync_with_domain "${domain}" &
        fi
    done

    wait
}

trap "trap - SIGTERM && kill 0 && echo exit..." SIGTERM SIGINT

main


================================================
FILE: hack/fmt-image-match.sh
================================================
#!/usr/bin/env bash

function check_match() {
    local image=$1
    local lines=$2
    for line in ${lines}; do
        if [[ "${line}" == *"/**" ]]; then
            if [[ "${image}" == "${line%\*\*}"* ]]; then
                return
            fi
        elif [[ "${line}" == *"/*" ]]; then
            if [[ "${image}" == "${line%\*}"* ]]; then
                if [[ "${image#"${line%\*}"}" != *"/"* ]]; then
                    return
                fi
            fi
        fi
    done

    echo "${image}"
}

function check_match_more() {
    local image=$1
    local lines=$2
    for line in ${lines}; do
        if [[ "${line}" == *"/**" ]]; then
            if [[ "${image}" == "${line%\*\*}"* ]]; then
                return
            fi
        fi
    done

    echo "${image}"
}

function format() {
    local file=$1
    local lines="$(cat "${file}")"
    for line in ${lines}; do
        if [[ "${line}" != *"*" ]]; then
            check_match  "${line}" "${lines}"
        fi
    done

    for line in ${lines}; do
        if [[ "${line}" == *"/**" ]]; then
            echo "${line}"
        elif [[ "${line}" == *"/*" ]]; then
            check_match_more  "${line}" "${lines}"
        fi
    done
}

export LC_ALL=C
file=$1

format "${file}" |
    sort -u |
    grep -v '^$' >$1.tmp && mv $1.tmp $1


================================================
FILE: hack/fmt-image.sh
================================================
#!/usr/bin/env bash

function filter_docker_library() {
    while read -r line; do
        if [[ $line =~ ^docker\.io/[^/]*$ ]]; then
            echo "docker.io/library/${line#docker.io/}"
        else
            echo "${line}"
        fi
    done
}

function filter_k8s_old() {
    while read -r line; do
        if [[ $line =~ ^k8s\.gcr\.io/.*$ ]]; then
            echo "registry.k8s.io/${line#k8s.gcr.io/}"
        else
            echo "${line}"
        fi
    done
}

cat $1 |
    filter_docker_library |
    filter_k8s_old >$1.tmp && mv $1.tmp $1


================================================
FILE: hack/fmt.sh
================================================
#!/usr/bin/env bash

export LC_ALL=C

cat $1 |
    sort -u |
    grep -v '^$' >$1.tmp && mv $1.tmp $1


================================================
FILE: hack/helper.sh
================================================
#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail

ROOT="${ROOT:-$(dirname "${BASH_SOURCE}")/..}"
DEFAULT_REGEX='^([a-z]+-)?[a-z]*[0-9]+(\.[0-9]+){1,2}'
SKOPEO="${SKOPEO:-skopeo}"
ROOT=$(realpath ${ROOT})
DOMAIN="${DOMAIN:-m.daocloud.io}"

function helper::replace_domain() {
    local domain="${1}"
    echo "${DOMAIN}/${domain}"
}

function helper::get_source() {
    local source="${1:-mirror.txt}"
    cat "${source}" | tr -d ' ' | grep -v -E '^$' | grep -v -E '^#'
}

function helper::exclude() {
    local exclude="${1:-exclude.txt}"
    local tmp=$(cat "${exclude}" | tr -d ' ' | grep -v -E '^$' | grep -v -E '^#' | tr '\n' '|')
    echo "${tmp%|}"
}


================================================
FILE: hack/merge-mirror.sh
================================================
#!/usr/bin/env bash

base_list="${1}"
used_list="${2}"
used_top="${3:-100}"

function used_top() {
    cat "${used_list}" | head -n "${used_top}"
}

function intersection_used() {
    sort "${base_list}" "${used_list}" | uniq -d
}

function fixed_docker() {
    grep "^docker\.io/library/" "${base_list}"
    grep "^docker\.io/library/" "${used_list}"
}

function fixed_k8s() {
    grep "^registry\.k8s\.io/" "${base_list}"
    grep "^registry\.k8s\.io/" "${used_list}"
}

function fixed_istio() {
    grep "^docker\.io/istio/" "${base_list}"
    grep "^docker\.io/istio/" "${used_list}"
}

cat <(used_top) \
    <(intersection_used) \
    <(fixed_docker) \
    <(fixed_k8s) | sort | uniq -u


================================================
FILE: hack/stats-not-sync.sh
================================================
#!/usr/bin/env bash

cat $1  | grep NOT-SYNCHRONIZED | awk '{print $3}' | grep ':' | tr ':' ' ' | awk '{print $1}' | uniq -c | sort -nrk 1


================================================
FILE: hack/verify-allows.sh
================================================
#!/usr/bin/env bash

file=$1

image=$2

function check_allows() {
    local file=$1
    local image=$2
    if [[ "${image}" == *":" ]]; then
        return 1
    fi
    while read line; do
        if [[ "${line}" == *"**" ]]; then
            if [[ "${image}" == "${line%\*\*}"* ]]; then
                return 0
            fi
        elif [[ "${line}" == *"*" ]]; then
            if [[ "${image}" == "${line%\*}"* ]]; then
                if [[ "${image#"${line%\*}"}" != *"/"* ]]; then
                    return 0
                fi
            fi
        elif [[ "${line}" == "${image%\:*}" ]]; then
            return 0
        fi
    done <"${file}"

    return 1
}

check_allows "${file}" "${image}"


================================================
FILE: hack/verify-docker-prefix.sh
================================================
#!/usr/bin/env bash

file=$1

cp ${file} ${file}.bak

cat ${file} | grep docker.io | grep library | sed 's#docker.io/library/#docker.io/#' >>${file}.bak

cat ${file} | grep -e "docker\.io/\w\+:\|docker\.io/\w\+$" | sed 's#docker.io/#docker.io/library/#' >>${file}.bak

$(dirname "${BASH_SOURCE}")/fmt.sh ${file}.bak

result=$(diff ${file} ${file}.bak)

if [[ "${result}" != "" ]]; then
    echo "Usually docker.io/* and docker.io/library/* appear in pairs "
    echo "Please run following command to fix the issue:"
    echo "cat <<EOF >> ${file}"
    echo "${result}" | grep "^>" | sed 's/^>\s\+//'
    echo "EOF"
    echo "./hack/fmt.sh ${file}"

    exit 1
fi

rm ${file}.bak


================================================
FILE: hack/verify-fmt-image.sh
================================================
#!/usr/bin/env bash

export LC_ALL=C

cp $1 $1.bak

$(dirname "${BASH_SOURCE}")/fmt-image.sh $1.bak

diff -c $1 $1.bak && rm $1.bak


================================================
FILE: hack/verify-fmt.sh
================================================
#!/usr/bin/env bash

export LC_ALL=C

cp $1 $1.bak

$(dirname "${BASH_SOURCE}")/fmt.sh $1.bak

diff -c $1 $1.bak && rm $1.bak


================================================
FILE: hack/verify-image-match.sh
================================================
#!/usr/bin/env bash

export LC_ALL=C

cp $1 $1.bak

$(dirname "${BASH_SOURCE}")/fmt-image-match.sh $1.bak

diff -c $1 $1.bak && rm $1.bak


================================================
FILE: hack/verify-image.sh
================================================
#!/usr/bin/env bash

file=$1

patch_url=$2

list=""
if [[ "${patch_url}" == "" ]]; then
    list=$(cat "${file}")
else 
    cp "${file}" "${file}.bak"
    git apply -R <(curl -fsSL "${patch_url}") || :
    list=$(diff --unified "${file}" "${file}.bak" | grep '^+\w' | sed 's/^+//' || :)
fi

failed=()
for image in ${list}; do
    image="${image%%\:*}"
    echo "Checking image: ${image}"
    raw=$(skopeo list-tags --no-creds --tls-verify=false --retry-times 3 "docker://${image}")
    if [[ $? -ne 0 ]]; then
        failed+=("not found ${image}")
        echo "Not found ${image}"
        continue
    fi
    if [[ $(echo "${raw}" | jq '.Tags | length') -eq 0 ]]; then
        failed+=("found ${image} but no tags")
        echo "Found ${image} but no tags"
        echo "${raw}"
        continue
    fi
done

if [[ ${#failed[@]} -ne 0 ]]; then
    echo "Failed images:"
    for image in "${failed[@]}"; do
        echo "  ${image}"
    done
    exit 1
fi


================================================
FILE: hack/verify-k8s-prefix.sh
================================================
#!/usr/bin/env bash

file=$1

result="$(cat ${file} | grep k8s.gcr.io/)"

if [[ "${result}" != "" ]]; then
    echo "Usually registry.k8s.io/* instead of k8s.gcr.io/*"
    echo "Please run following command to fix the issue:"
    echo "cat ${file} | sed 's#k8s.gcr.io/#registry.k8s.io/#' >${file}.bak"
    echo "mv ${file}.bak ${file}"
    echo "./hack/fmt.sh ${file}"

    exit 1
fi
Download .txt
gitextract_k3b5ogrq/

├── .gitee/
│   └── ISSUE_TEMPLATE/
│       └── allows-image.yml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── allows-image.yml
│   │   └── sync-image.yml
│   └── workflows/
│       ├── ci-bot.yml
│       ├── cidn-runner.yml
│       ├── sync-image.yml
│       ├── update-allows-list.yml
│       └── verify-pr.yml
├── LICENSE
├── README.md
├── allows.txt
├── docs/
│   └── local-cache/
│       └── README.md
└── hack/
    ├── badge.sh
    ├── correct-image.sh
    ├── diff-image.sh
    ├── diff.sh
    ├── fmt-image-match.sh
    ├── fmt-image.sh
    ├── fmt.sh
    ├── helper.sh
    ├── merge-mirror.sh
    ├── stats-not-sync.sh
    ├── verify-allows.sh
    ├── verify-docker-prefix.sh
    ├── verify-fmt-image.sh
    ├── verify-fmt.sh
    ├── verify-image-match.sh
    ├── verify-image.sh
    └── verify-k8s-prefix.sh
Condensed preview — 29 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (95K chars).
[
  {
    "path": ".gitee/ISSUE_TEMPLATE/allows-image.yml",
    "chars": 1488,
    "preview": "name: Allows Image\ndescription: 添加白名单 (人工审核)\nlabels:\n- allows image\nbody:\n- type: markdown\n  attributes:\n    value: |\n  "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/allows-image.yml",
    "chars": 1488,
    "preview": "name: Allows Image\ndescription: 添加白名单 (人工审核)\nlabels:\n- allows image\nbody:\n- type: markdown\n  attributes:\n    value: |\n  "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/sync-image.yml",
    "chars": 1012,
    "preview": "name: Sync Image\ndescription: 同步一个镜像 (需要 Image 已在白名单里)\nlabels:\n- sync image\nbody:\n- type: markdown\n  attributes:\n    val"
  },
  {
    "path": ".github/workflows/ci-bot.yml",
    "chars": 5081,
    "preview": "name: CI Bot\non:\n  issue_comment:\n    types:\n      - created\n\n  pull_request_review_comment:\n    types:\n      - created\n"
  },
  {
    "path": ".github/workflows/cidn-runner.yml",
    "chars": 453,
    "preview": "name: CIDN Runner\nrun-name: CIDN Runner ${{ github.run_number }}\n\non:\n  schedule:\n    - cron: \"0,30 * * * *\"\n\n  workflow"
  },
  {
    "path": ".github/workflows/sync-image.yml",
    "chars": 4953,
    "preview": "name: Target Sync Image\nrun-name: Target Sync ${{ github.event.issue.title }} by @${{ github.actor }}\n\non:\n  issues:\n   "
  },
  {
    "path": ".github/workflows/update-allows-list.yml",
    "chars": 1151,
    "preview": "name: Update allows list\n\non:\n  push:\n    paths:\n    - allows.txt\n    branches:\n    - main\n  workflow_dispatch:\n\njobs:\n "
  },
  {
    "path": ".github/workflows/verify-pr.yml",
    "chars": 1023,
    "preview": "name: Verify PR\n\non:\n  pull_request_target:\n    branches: [main]\n    paths:\n      - 'mirror.txt'\n      - 'allows.txt'\n\np"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 5044,
    "preview": "# public-image-mirror\n\n源仓库 [Github](https://github.com/DaoCloud/public-image-mirror)  \nMirror 仓库 [Gitee](https://gitee.c"
  },
  {
    "path": "allows.txt",
    "chars": 32940,
    "preview": "code.forgejo.org/forgejo/forgejo\ncode.forgejo.org/forgejo/runner\ncodeberg.org/forgejo/forgejo\ncontainer-registry.oracle."
  },
  {
    "path": "docs/local-cache/README.md",
    "chars": 1405,
    "preview": "# 部署内网缓存\n\n## 简介\n\n本地缓存部署用于在内网环境中加速镜像拉取,减少对外网的依赖。通过设置一个本地镜像仓库,您可以缓存常用的镜像。\n\n## 部署步骤\n\n1. **准备环境**  \n\n确保已安装 Docker 和 Docker C"
  },
  {
    "path": "hack/badge.sh",
    "chars": 725,
    "preview": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nQUICKLY=\"${QUICKLY:-}\"\ncat *\"_sync.log\" > \"sync.log\""
  },
  {
    "path": "hack/correct-image.sh",
    "chars": 832,
    "preview": "#!/usr/bin/env bash\n\nfunction guess_image() {\n    local image=\"${1}\"\n\n    image=\"${image// /}\"\n    image=\"${image#\\/}\"\n "
  },
  {
    "path": "hack/diff-image.sh",
    "chars": 12077,
    "preview": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\n# Output more information that is out of synchronize"
  },
  {
    "path": "hack/diff.sh",
    "chars": 1938,
    "preview": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nsource \"$(dirname \"${BASH_SOURCE}\")/helper.sh\"\ncd \"$"
  },
  {
    "path": "hack/fmt-image-match.sh",
    "chars": 1324,
    "preview": "#!/usr/bin/env bash\n\nfunction check_match() {\n    local image=$1\n    local lines=$2\n    for line in ${lines}; do\n       "
  },
  {
    "path": "hack/fmt-image.sh",
    "chars": 556,
    "preview": "#!/usr/bin/env bash\n\nfunction filter_docker_library() {\n    while read -r line; do\n        if [[ $line =~ ^docker\\.io/[^"
  },
  {
    "path": "hack/fmt.sh",
    "chars": 102,
    "preview": "#!/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",
    "chars": 675,
    "preview": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nROOT=\"${ROOT:-$(dirname \"${BASH_SOURCE}\")/..}\"\nDEFAU"
  },
  {
    "path": "hack/merge-mirror.sh",
    "chars": 692,
    "preview": "#!/usr/bin/env bash\n\nbase_list=\"${1}\"\nused_list=\"${2}\"\nused_top=\"${3:-100}\"\n\nfunction used_top() {\n    cat \"${used_list}"
  },
  {
    "path": "hack/stats-not-sync.sh",
    "chars": 139,
    "preview": "#!/usr/bin/env bash\n\ncat $1  | grep NOT-SYNCHRONIZED | awk '{print $3}' | grep ':' | tr ':' ' ' | awk '{print $1}' | uni"
  },
  {
    "path": "hack/verify-allows.sh",
    "chars": 709,
    "preview": "#!/usr/bin/env bash\n\nfile=$1\n\nimage=$2\n\nfunction check_allows() {\n    local file=$1\n    local image=$2\n    if [[ \"${imag"
  },
  {
    "path": "hack/verify-docker-prefix.sh",
    "chars": 679,
    "preview": "#!/usr/bin/env bash\n\nfile=$1\n\ncp ${file} ${file}.bak\n\ncat ${file} | grep docker.io | grep library | sed 's#docker.io/lib"
  },
  {
    "path": "hack/verify-fmt-image.sh",
    "chars": 132,
    "preview": "#!/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 &"
  },
  {
    "path": "hack/verify-fmt.sh",
    "chars": 126,
    "preview": "#!/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 $"
  },
  {
    "path": "hack/verify-image-match.sh",
    "chars": 138,
    "preview": "#!/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"
  },
  {
    "path": "hack/verify-image.sh",
    "chars": 958,
    "preview": "#!/usr/bin/env bash\n\nfile=$1\n\npatch_url=$2\n\nlist=\"\"\nif [[ \"${patch_url}\" == \"\" ]]; then\n    list=$(cat \"${file}\")\nelse \n"
  },
  {
    "path": "hack/verify-k8s-prefix.sh",
    "chars": 384,
    "preview": "#!/usr/bin/env bash\n\nfile=$1\n\nresult=\"$(cat ${file} | grep k8s.gcr.io/)\"\n\nif [[ \"${result}\" != \"\" ]]; then\n    echo \"Usu"
  }
]

About this extraction

This page contains the full source code of the DaoCloud/public-image-mirror GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 29 files (87.5 KB), approximately 26.9k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!