cover

Container Registry 選擇:自建 Harbor vs 雲端託管

Container Registry 是容器化工作流程的核心基礎設施。所有用 Docker 打包的服務,最終都需要一個集中的映像檔倉庫來存放、版本管理、安全掃描和分發。選擇哪一種 Registry,直接影響 CI/CD 的速度、部署的可靠度、安全性,以及長期的維運成本。

大方向上,選擇分為兩條路:自建(Harbor、私有 Docker Registry)或雲端託管(AWS ECR、Google Artifact Registry、Azure ACR、Docker Hub、GitHub Container Registry)。自建的好處是完全掌控,但代價是維運負擔;雲端託管省心省力,但會被綁在特定雲端平台上,而且流量大時費用可能超出預期。

這篇文章不只是功能比較表,而是從實際部署場景出發,分析在不同團隊規模、不同架構下,哪一種 Registry 最合理。

架構概覽

flowchart TD
    subgraph 自建["自建 Registry"]
        Harbor["Harbor\n企業級功能\n安全掃描 / RBAC"]
        Private["Docker Registry\n輕量自建"]
    end

    subgraph 雲端["雲端託管 Registry"]
        ECR["AWS ECR\n整合 ECS/EKS"]
        GAR["Google AR\n整合 GKE"]
        ACR["Azure ACR\n整合 AKS"]
        DockerHub["Docker Hub\n公開映像生態"]
        GHCR["ghcr.io\n整合 GitHub Actions"]
    end

    選擇{{"選擇 Registry"}}
    選擇 -->|完全掌控\n合規需求| 自建
    選擇 -->|省心省力\n原生整合| 雲端

    Harbor -->|"安全掃描\nReplication\n無 Rate Limit"| 適合大型團隊["大型團隊 / 合規場景"]
    ECR -->|"Lifecycle Policy\nIAM 整合"| 適合AWS["AWS 生態系"]
    GAR -->|"多格式支援\nBinary Auth"| 適合GCP["GCP 生態系"]
    ACR -->|"Geo-replication\nACR Tasks"| 適合Azure["Azure 生態系"]
    DockerHub -->|"最大公開生態\n有 Rate Limit"| 適合小型["小團隊 / 開源"]
    GHCR -->|"零設定認證\n公開免費"| 適合GH["GitHub Actions 用戶"]

架構概覽:Registry 選項與部署流程

flowchart TB
  subgraph CI["CI/CD Pipeline"]
    Build[Build Image]
  end

  subgraph SelfHosted["自建 Registry"]
    Harbor[Harbor\n完整企業功能]
    PrivateReg[Docker Registry\n輕量自建]
  end

  subgraph CloudManaged["雲端託管 Registry"]
    ECR[AWS ECR]
    GAR[Google Artifact Registry]
    ACR[Azure ACR]
    DockerHub[Docker Hub]
    GHCR[GitHub Container Registry\nghcr.io]
  end

  subgraph Deploy["部署目標"]
    ECS[AWS ECS / EKS]
    GKE[Google GKE]
    AKS[Azure AKS]
    SelfHost[Self-hosted\nDocker / K8s]
  end

  Build -->|docker push| Harbor
  Build -->|docker push| PrivateReg
  Build -->|docker push| ECR
  Build -->|docker push| GAR
  Build -->|docker push| ACR
  Build -->|docker push| DockerHub
  Build -->|docker push| GHCR

  Harbor -->|docker pull| SelfHost
  Harbor -->|docker pull| ECS
  PrivateReg -->|docker pull| SelfHost

  ECR -->|原生整合| ECS
  GAR -->|原生整合| GKE
  ACR -->|原生整合| AKS

  DockerHub -->|docker pull| SelfHost
  DockerHub -->|docker pull| ECS
  DockerHub -->|docker pull| GKE

  GHCR -->|docker pull| SelfHost
  GHCR -->|docker pull| ECS

CI/CD pipeline build 完映像檔後,根據團隊選用的 Registry 推送到對應的倉庫。雲端託管的 Registry 與各自的容器編排服務有原生整合(ECR + ECS/EKS、GAR + GKE、ACR + AKS),認證和網路都比較順暢。自建 Harbor 則可以對接任何部署環境,但需要自行處理網路可達性和認證機制。

核心概念:各 Registry 深入比較

1. 自建 Harbor

Harbor 是 CNCF 畢業專案,是目前功能最完整的開源 Container Registry。適合對映像檔管理有高度控制需求的團隊。

優點:

  • 完全掌控:資料完全在自己的基礎設施上,不會因為第三方服務斷線而影響部署。符合某些產業的合規要求(例如金融、醫療),資料不能離開特定的網路邊界。
  • 安全掃描整合:內建 Trivy 掃描器,每次 push 映像檔自動掃描 CVE。可以設定策略:有 Critical 漏洞的映像檔禁止 pull,強制修復後才能部署。
  • 完整 RBAC:Project 層級的存取控制,可以精細到「某個帳號只能 pull 特定 Project 的映像檔」。搭配 Robot Account 給 CI pipeline 用,不需要用個人帳號。
  • 無頻寬費用:在自己的網路內傳輸映像檔不產生額外費用。對於頻繁 build/deploy 的團隊,這筆省下來的費用很可觀。
  • Replication 與多站點同步:支援 pull-based 和 push-based 的映像檔同步,可以在多個資料中心之間複製映像檔。

缺點:

  • 維運負擔:Harbor 本身需要維護(升級、備份、監控)。底層依賴 PostgreSQL、Redis、S3-compatible storage,每一個元件都可能出問題。
  • HA 設定複雜:Harbor 單節點掛了,所有環境都拉不到映像檔。要做 HA 需要多節點部署 + 共享儲存 + 負載均衡器,架構複雜度大幅上升。
  • 資源消耗:建議至少 4GB RAM、50GB disk。如果映像檔數量多,儲存空間需求會快速增長。

更多 Harbor 的部署細節與設定,請參考 Harbor(自建)

2. AWS ECR(Elastic Container Registry)

ECR 是 AWS 的託管 Container Registry,與 AWS 生態系深度整合。

  • 定價模型:按儲存量($0.10/GB/月)和資料傳輸費計費。同一 Region 內 pull 免費,跨 Region 或傳到 Internet 需要付傳輸費。Private Repository 無數量限制,Public Repository 有免費額度。
  • ECS/EKS 整合:ECS task definition 和 EKS Pod 可以直接引用 ECR 映像檔,認證透過 IAM Role 自動處理,不需要額外設定 docker login。
  • Lifecycle Policy:可以設定自動清理規則,例如「保留最近 10 個 tag」或「刪除超過 30 天的 untagged 映像檔」。這是 ECR 最實用的功能之一,避免儲存費用無限增長。
  • 映像檔掃描:支援基本掃描(免費,用 Clair)和進階掃描(Amazon Inspector,需要額外費用)。進階掃描支援持續監控,發現新 CVE 時會主動通知。
  • 跨帳戶/跨 Region 複製:支援映像檔跨 AWS 帳戶和跨 Region 自動複製,適合多帳戶架構(dev/staging/prod 各有獨立 AWS 帳戶)。

3. Google Artifact Registry(原 GCR)

Google 已將 GCR(Google Container Registry)升級為 Artifact Registry,功能更完整,支援多種套件格式(Docker、npm、Maven、Python 等)。

  • GKE 整合:GKE 節點透過 Workload Identity 自動取得 Artifact Registry 的讀取權限,零設定即可 pull 映像檔。
  • 定價:儲存費用根據所在 Region 的 Cloud Storage 費率計算(約 $0.026/GB/月,Standard 等級)。同 Region 內拉取免費,跨 Region 按網路傳輸費計費。
  • 漏洞掃描:整合 Container Analysis API,支援自動掃描和按需掃描。與 Binary Authorization 搭配,可以強制只有通過掃描的映像檔才能部署到 GKE。
  • IAM 整合:使用 Google Cloud IAM 統一管理權限,可以精細到 repository 層級。

4. Azure ACR(Azure Container Registry)

ACR 是 Azure 的託管 Registry,與 Azure 生態系整合。

  • AKS 整合:ACR 與 AKS 之間透過 Managed Identity 認證,設定 az aks update --attach-acr 一行指令就能讓 AKS 叢集拉取 ACR 映像檔。
  • Geo-replication:Premium 層級支援跨地區複製,映像檔自動同步到多個 Azure Region。對於全球部署的應用,可以讓各地的 AKS 叢集從最近的 ACR 副本 pull,降低延遲。
  • ACR Tasks:內建的 build 服務,可以直接在 ACR 上 build 映像檔,不需要在 CI 環境安裝 Docker。支援多步驟 task 和自動觸發(git commit、base image 更新時自動 rebuild)。
  • 定價:分 Basic(0.667/天)、Premium($1.667/天)三個層級,功能和儲存額度不同。

5. Docker Hub

Docker Hub 是最老牌的公共 Container Registry,也是 Docker 的預設 Registry。

  • 免費層級限制:免費帳戶只能有 1 個私有 Repository。2020 年後,免費帳戶的 pull 有頻率限制(anonymous: 100 pulls/6hr,authenticated: 200 pulls/6hr)。
  • Rate Limiting 影響:這是 Docker Hub 最大的痛點。CI pipeline 頻繁 pull base image(如 node:20-alpinepostgres:16),很容易觸發限制,導致 build 失敗。解法是設定 Pull-through Cache(Harbor 支援)或切換到其他 Registry。
  • 公開映像檔生態:絕大多數的官方映像檔(Node.js、Python、PostgreSQL、Nginx 等)都託管在 Docker Hub 上。即使你的私有映像檔不放 Docker Hub,build 時的 base image 通常還是從這裡拉。
  • 定價:Pro(9/人/月)、Business($24/人/月)。

6. GitHub Container Registry(ghcr.io)

GHCR 是 GitHub 提供的 Container Registry,與 GitHub Actions 深度整合。

  • GitHub Actions 整合:使用 GITHUB_TOKEN 即可在 Actions workflow 中 push/pull 映像檔,不需要額外設定 secret。映像檔可以與 Repository 關聯,在 repo 頁面直接看到 Packages。
  • 定價:公開映像檔免費且無頻率限制。私有映像檔的儲存和傳輸包含在 GitHub 方案的額度內(Free: 500MB storage, 1GB transfer/月;Pro: 2GB storage, 10GB transfer/月)。
  • 適用場景:開源專案的首選(免費且無限制)。對於已經用 GitHub Actions 做 CI/CD 的團隊,ghcr.io 是最順手的選擇,不需要額外管理認證和帳號。

功能比較表

特性Harbor (自建)AWS ECRGoogle ARAzure ACRDocker Hubghcr.io
費用模型自己的硬體成本按儲存+傳輸按儲存+傳輸按層級月費按方案月費包含在 GitHub 方案
安全掃描Trivy (內建)Inspector / ClairContainer AnalysisDefenderSnyk 整合無內建
RBACProject 層級IAM PolicyIAM 整合Azure RBACOrg/TeamOrg/Repo 權限
HA / 高可用需自建AWS 管理Google 管理Azure 管理服務商管理GitHub 管理
Geo-replicationReplication 功能跨 Region 複製Multi-regionPremium 才有
Lifecycle 清理Retention PolicyLifecycle Policy清理政策保留原則需手動無自動清理
CI/CD 整合任何 CICodePipeline / 任何Cloud Build / 任何DevOps / 任何任何GitHub Actions 最佳
映像簽章Notary / Cosign簽章驗證Binary AuthorizationContent Trust付費方案
Rate Limiting無(自建)有(免費帳戶)公開免費無限
Private Repos無限制無限制無限制依層級免費 1 個依方案額度
最佳搭配任何環境ECS / EKSGKEAKS公共映像GitHub Actions

部署模式:不用自建 Harbor 的幾種常見架構

不是每個團隊都需要自建 Harbor。如果你的工作負載主要在雲端,用雲端託管的 Registry 通常更省事。以下是三種常見的部署模式。

模式一:Cloud-native(全雲端)

CI (GitHub Actions / GitLab CI)
  → docker build
  → docker push to ECR
  → deploy to ECS / EKS

所有環節都在同一個雲端平台上。映像檔在同 Region 內傳輸免費,IAM 認證自動處理,沒有額外的基礎設施需要維護。適合團隊全部在 AWS/GCP/Azure 上的場景。

模式二:Hybrid(混合架構)

CI (自建 GitLab Runner / Jenkins)
  → docker build on-premise
  → docker push to ECR / Artifact Registry
  → deploy to cloud (ECS / GKE)

Build 在地端進行(可能是因為 code 不能離開內部網路),映像檔推到雲端 Registry,再部署到雲端。需要注意上傳頻寬和 push 時的網路傳輸費用。

模式三:Multi-cloud(多雲部署)

CI → docker push to ECR (primary)
  → ECR replication to other regions
  → deploy to AWS EKS (主要)
  → deploy to GKE (備援)
  → deploy to self-hosted K8s (特殊需求)

以一個雲端 Registry 為主,映像檔跨雲或跨 Region 複製。需要在非主要雲端設定跨帳號存取權限。這種模式的複雜度較高,但適合需要避免單一雲端供應商鎖定的場景。

實作範例

範例一:各 Registry 的 docker login / push / pull

# ===== Docker Hub =====
docker login -u myuser -p mytoken
docker build -t myuser/myapp:v1.0.0 .
docker push myuser/myapp:v1.0.0
 
# ===== AWS ECR =====
# 透過 AWS CLI 取得 ECR 登入 token(有效期 12 小時)
aws ecr get-login-password --region ap-northeast-1 \
  | docker login --username AWS --password-stdin 123456789.dkr.ecr.ap-northeast-1.amazonaws.com
 
docker build -t 123456789.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:v1.0.0 .
docker push 123456789.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:v1.0.0
 
# ===== Google Artifact Registry =====
# 設定 Docker credential helper
gcloud auth configure-docker asia-east1-docker.pkg.dev
 
docker build -t asia-east1-docker.pkg.dev/my-project/my-repo/myapp:v1.0.0 .
docker push asia-east1-docker.pkg.dev/my-project/my-repo/myapp:v1.0.0
 
# ===== Azure ACR =====
az acr login --name myregistry
 
docker build -t myregistry.azurecr.io/myapp:v1.0.0 .
docker push myregistry.azurecr.io/myapp:v1.0.0
 
# ===== GitHub Container Registry =====
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
 
docker build -t ghcr.io/myorg/myapp:v1.0.0 .
docker push ghcr.io/myorg/myapp:v1.0.0
 
# ===== 自建 Harbor =====
docker login harbor.example.com -u admin -p Harbor12345
 
docker build -t harbor.example.com/myproject/myapp:v1.0.0 .
docker push harbor.example.com/myproject/myapp:v1.0.0

每個 Registry 的映像檔命名規則不同:Docker Hub 用 username/image,ECR 用完整的 AWS 帳戶 endpoint,Artifact Registry 用 region-docker.pkg.dev/project/repo/image,ACR 用 registry.azurecr.io/image,GHCR 用 ghcr.io/org/image。在 CI pipeline 裡要根據目標 Registry 正確設定 image tag。

範例二:GitLab CI Pipeline 推送映像檔到 AWS ECR

# .gitlab-ci.yml - Build and push to AWS ECR
variables:
  AWS_REGION: "ap-northeast-1"
  AWS_ACCOUNT_ID: "123456789012"
  ECR_REGISTRY: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
  ECR_REPOSITORY: "myapp"
  IMAGE: "${ECR_REGISTRY}/${ECR_REPOSITORY}"
 
stages:
  - test
  - build
  - deploy
 
test:
  stage: test
  image: node:20-alpine
  script:
    - npm ci
    - npm test
 
build:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  before_script:
    # 安裝 AWS CLI
    - apk add --no-cache aws-cli
    # ECR 登入(使用 GitLab CI/CD Variables 裡設定的 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY)
    - aws ecr get-login-password --region $AWS_REGION
      | docker login --username AWS --password-stdin $ECR_REGISTRY
  script:
    # 確保 ECR Repository 存在(不存在則建立)
    - aws ecr describe-repositories --repository-names $ECR_REPOSITORY --region $AWS_REGION
      || aws ecr create-repository --repository-name $ECR_REPOSITORY --region $AWS_REGION
    # Build and push
    - docker build
      --label "git.commit=${CI_COMMIT_SHA}"
      --label "git.branch=${CI_COMMIT_REF_NAME}"
      -t ${IMAGE}:${CI_COMMIT_SHA}
      -t ${IMAGE}:${CI_COMMIT_REF_SLUG}
      .
    - docker push ${IMAGE}:${CI_COMMIT_SHA}
    - docker push ${IMAGE}:${CI_COMMIT_REF_SLUG}
    # 如果是 release tag,額外推一份帶版本號的
    - |
      if [ -n "$CI_COMMIT_TAG" ]; then
        docker tag ${IMAGE}:${CI_COMMIT_SHA} ${IMAGE}:${CI_COMMIT_TAG}
        docker push ${IMAGE}:${CI_COMMIT_TAG}
      fi
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
    - if: $CI_COMMIT_TAG =~ /^v\d+/
 
deploy:dev:
  stage: deploy
  image: amazon/aws-cli:latest
  environment:
    name: dev
  script:
    # 更新 ECS service 使用新的映像檔
    - aws ecs update-service
      --cluster my-cluster
      --service myapp-service
      --force-new-deployment
      --region $AWS_REGION
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

這個 pipeline 的重點:before_script 用 AWS CLI 取得 ECR 的短期 token 登入。build job 會先檢查 ECR repository 是否存在,不存在就自動建立。deploy 階段用 aws ecs update-service --force-new-deployment 觸發 ECS 重新拉取映像檔。

範例三:ECR Lifecycle Policy(自動清理舊映像檔)

{
  "rules": [
    {
      "rulePriority": 1,
      "description": "保留最近 5 個帶版本號的 tag (v*)",
      "selection": {
        "tagStatus": "tagged",
        "tagPrefixList": ["v"],
        "countType": "imageCountMoreThan",
        "countNumber": 5
      },
      "action": {
        "type": "expire"
      }
    },
    {
      "rulePriority": 2,
      "description": "保留最近 10 個 commit SHA tag",
      "selection": {
        "tagStatus": "tagged",
        "tagPrefixList": ["sha-"],
        "countType": "imageCountMoreThan",
        "countNumber": 10
      },
      "action": {
        "type": "expire"
      }
    },
    {
      "rulePriority": 10,
      "description": "刪除超過 14 天的 untagged 映像檔",
      "selection": {
        "tagStatus": "untagged",
        "countType": "sinceImagePushed",
        "countUnit": "days",
        "countNumber": 14
      },
      "action": {
        "type": "expire"
      }
    },
    {
      "rulePriority": 20,
      "description": "刪除超過 30 天的所有非版本號映像檔",
      "selection": {
        "tagStatus": "any",
        "countType": "sinceImagePushed",
        "countUnit": "days",
        "countNumber": 30
      },
      "action": {
        "type": "expire"
      }
    }
  ]
}
# 套用 Lifecycle Policy 到 ECR repository
aws ecr put-lifecycle-policy \
  --repository-name myapp \
  --lifecycle-policy-text file://lifecycle-policy.json \
  --region ap-northeast-1

Lifecycle Policy 是 ECR 管理儲存成本的核心機制。規則按 rulePriority 從小到大評估,符合條件的映像檔會被標記為過期並在 24 小時內自動刪除。建議至少設定 untagged 映像檔的清理規則,CI 每次 build 都會產生中間層映像檔,不清理的話儲存費用會持續累積。

範例四:GitHub Actions 推送映像檔到 ghcr.io

# .github/workflows/build-push.yml
name: Build and Push to GHCR
 
on:
  push:
    branches: [main]
    tags: ['v*']
  pull_request:
    branches: [main]
 
env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}
 
jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
 
    steps:
      - name: Checkout
        uses: actions/checkout@v4
 
      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
 
      - name: Extract metadata (tags, labels)
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha
 
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

這個 workflow 的亮點:使用 docker/metadata-action 自動根據 git ref 產生合適的 tag(branch name、PR number、semver、commit SHA)。permissions.packages: write 搭配 GITHUB_TOKEN 就能 push 到 ghcr.io,不需要額外建立 Personal Access Token。cache-from: type=gha 利用 GitHub Actions 的 cache 加速 Docker build。PR 觸發時只 build 不 push(push: ${{ github.event_name != 'pull_request' }}),避免把未 review 的映像檔推到 Registry。

常見問題與風險

  • Docker Hub Rate Limiting 導致 CI 失敗:這是最常見的問題。CI pipeline 頻繁 pull 公開映像檔(node:20-alpinepostgres:16),免費帳戶很容易觸發 100 pulls/6hr 的限制。錯誤訊息通常是 toomanyrequests: You have reached your pull rate limit。解法有三:1) 在 CI 環境做 authenticated pull(提高到 200/6hr);2) 設定 Pull-through Cache(Harbor 或雲端 Registry 都支援);3) 把常用的 base image mirror 到自己的 Registry。

  • 映像檔命名規則搞混:不同 Registry 的 image tag 格式完全不同。從 Docker Hub 遷移到 ECR 時,所有 Dockerfile 的 FROM 指令和 docker-compose 的 image 欄位都需要更新。如果 CI 和部署設定沒有同步修改,會出現 push 到 A 但從 B pull 的錯誤。建議在 CI 設定中用變數管理 Registry 前綴,換 Registry 時只需改變數。

  • 雲端 Registry 的跨 Region 傳輸費用:映像檔存在 us-east-1 的 ECR,但 EKS 叢集在 ap-northeast-1,每次 pull 都要付跨 Region 傳輸費。一個 500MB 的映像檔,100 個 Pod 的叢集擴展時就是 50GB 的傳輸量。解法:啟用 ECR 的跨 Region 複製,讓各 Region 有本地副本。

  • 認證 Token 過期:ECR 的 login token 只有 12 小時效期。如果 CI job 跑超過 12 小時(大型 build),中途 push 會失敗。K8s 環境中,如果 imagePullSecret 的 token 過期,新的 Pod 會拉不到映像檔。解法:ECR 用 credential helper 自動更新;K8s 用 IAM Role for Service Account(IRSA)而非靜態 token。

  • 映像檔大小失控:沒有做 multi-stage build,映像檔動輒 1-2GB,push/pull 時間長,儲存費用高,部署時拉取慢影響啟動速度。解法:使用 multi-stage build 和 alpine-based base image;定期檢查映像檔 layer 大小(docker history);設定映像檔大小上限的 CI 檢查。

  • Registry 掛掉的 blast radius:不管用自建還是雲端,Registry 掛掉時已經在跑的容器不受影響(映像檔已在本地),但新部署、scaling、和 rollback 都會失敗。已 pull 到節點的映像檔由 containerd/Docker 的本地快取管理,但節點重啟後快取可能消失。因此 Registry 的可用性直接決定了你的部署可用性。

  • 安全性:映像檔供應鏈攻擊:從公開 Registry pull 的映像檔可能被植入惡意程式。2021 年就發生過 Docker Hub 上的官方映像檔被上游套件污染的事件。解法:只從可信任來源 pull base image;啟用映像檔簽章驗證(Cosign / Notary);在 Registry 和 CI 各設一層安全掃描。

如何選擇:決策指引

  1. 只在一個雲端平台上:用該平台的原生 Registry(ECR、Artifact Registry、ACR)。整合最好、效能最佳、管理最簡單。
  2. 主要用 GitHub Actions 做 CI/CD:ghcr.io 是最順手的選擇,認證零設定。
  3. 需要完全掌控、合規要求嚴格:自建 Harbor。
  4. 預算有限的小團隊:Docker Hub Pro($5/月)或 ghcr.io 免費方案。
  5. 多雲架構:選一個主要的雲端 Registry,搭配跨 Region/跨雲複製。

不需要一開始就做出最完美的選擇。很多團隊是從 Docker Hub 開始,遇到 rate limiting 後遷移到 ECR 或 ghcr.io,等團隊規模和安全需求增長後再考慮自建 Harbor。Registry 遷移的成本主要在於修改 CI 設定和部署檔案,映像檔本身可以用 crane copyskopeo copy 批量搬遷。

優點(使用雲端託管 Registry)

  • 零維運成本,不需要管理基礎設施
  • 與雲端容器服務原生整合,認證和網路自動處理
  • 內建 HA 和備份,SLA 有保障
  • 按用量計費,小規模時成本極低

缺點 / 限制(使用雲端託管 Registry)

  • 供應商鎖定,遷移到其他雲端需要調整 CI/CD 設定
  • 大量映像檔傳輸時,費用可能超出預期
  • 部分進階功能(安全掃描、geo-replication)需要付費方案
  • 安全掃描和 RBAC 的精細度通常不如 Harbor

延伸閱讀