Agent-almanac setup-container-registry

install
source · Clone the upstream repo
git clone https://github.com/pjt222/agent-almanac
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/ja/skills/setup-container-registry" ~/.claude/skills/pjt222-agent-almanac-setup-container-registry-481df5 && rm -rf "$T"
manifest: i18n/ja/skills/setup-container-registry/SKILL.md
source content

コンテナレジストリのセットアップ

セキュリティスキャン、アクセス制御、自動CI/CD統合を備えた本番対応コンテナレジストリを設定します。

使用タイミング

  • 組織向けプライベートコンテナレジストリのセットアップ
  • Docker Hubからセルフホステッドまたは代替レジストリへの移行
  • CI/CDパイプラインへのイメージ脆弱性スキャンの実装
  • マルチアーキテクチャイメージ(amd64、arm64)のマニフェスト管理
  • イメージ署名と出所検証の強制
  • 自動イメージクリーンアップと保持ポリシーの設定

入力

  • 必須: DockerまたはPodmanがローカルにインストール済み
  • 必須: レジストリ認証情報(個人アクセストークン、サービスアカウント)
  • 任意: Harborデプロイ向けセルフホステッドインフラ
  • 任意: レジストリ統合向けKubernetesクラスター
  • 任意: イメージ署名向けCosign/Notary
  • 任意: 脆弱性スキャン向けTrivyまたはClair

手順

完全な設定ファイルとテンプレートは拡張サンプルを参照してください。

ステップ1: GitHub Container Registry(ghcr.io)の設定

個人アクセストークンとCI/CD統合でGitHub Container Registryをセットアップします。

# Create GitHub Personal Access Token
# Go to: Settings → Developer settings → Personal access tokens → Tokens (classic)
# Required scopes: write:packages, read:packages, delete:packages

# Login to ghcr.io
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

# Verify login
docker info | grep -A 5 "Registry:"

# Tag image for ghcr.io
docker tag myapp:latest ghcr.io/USERNAME/myapp:latest
docker tag myapp:latest ghcr.io/USERNAME/myapp:v1.0.0

# Push image
docker push ghcr.io/USERNAME/myapp:latest
docker push ghcr.io/USERNAME/myapp:v1.0.0

# Configure in GitHub Actions
cat > .github/workflows/docker-build.yml <<'EOF'
name: Build and Push Docker Image

on:
  push:
    branches: [main]
    tags: ['v*']

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        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,prefix={{branch}}-

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
EOF

# Make package public (default is private)
# Go to: github.com/USERNAME?tab=packages → Select package → Package settings → Change visibility

# Pull image (public packages don't require authentication)
docker pull ghcr.io/USERNAME/myapp:latest

期待結果: GitHubトークンにパッケージ権限があります。Dockerログインが成功します。イメージが適切なタグでghcr.ioにプッシュされます。GitHub Actionsワークフローが自動タグ付きマルチアーキテクチャイメージをビルドします。パッケージの可視性が正しく設定されます。

失敗時: 認証エラーの場合、トークンに

write:packages
スコープがあり有効期限が切れていないことを確認します。プッシュ失敗の場合、リポジトリ名がイメージ名と一致することを確認します(大文字小文字の区別あり)。ワークフロー失敗の場合、
permissions: packages: write
が設定されていることを確認します。公開パッケージがアクセスできない場合、可視性変更が伝播するまで最大10分待ちます。

ステップ2: Docker Hubと自動ビルドの設定

アクセストークンと脆弱性スキャンでDocker Hubリポジトリをセットアップします。

# Create Docker Hub access token
# Go to: hub.docker.com → Account Settings → Security → New Access Token

# Login to Docker Hub
echo $DOCKERHUB_TOKEN | docker login -u USERNAME --password-stdin

# Create repository
# Go to: hub.docker.com → Repositories → Create Repository
# Select: public or private, enable vulnerability scanning (Pro/Team plan)

# Tag for Docker Hub
docker tag myapp:latest USERNAME/myapp:latest
docker tag myapp:latest USERNAME/myapp:v1.0.0

# Push to Docker Hub
docker push USERNAME/myapp:latest
docker push USERNAME/myapp:v1.0.0

# Configure automated builds (legacy feature, deprecated)
# Modern approach: Use GitHub Actions with Docker Hub

cat > .github/workflows/dockerhub.yml <<'EOF'
name: Docker Hub Push

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64,linux/arm/v7
          push: true
          tags: |
            ${{ secrets.DOCKERHUB_USERNAME }}/myapp:latest
            ${{ secrets.DOCKERHUB_USERNAME }}/myapp:${{ github.ref_name }}
          build-args: |
            BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
            VCS_REF=${{ github.sha }}

      - name: Update Docker Hub description
        uses: peter-evans/dockerhub-description@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
          repository: ${{ secrets.DOCKERHUB_USERNAME }}/myapp
          readme-filepath: ./README.md
EOF

# View vulnerability scan results
# Go to: hub.docker.com → Repository → Tags → View scan results

# Configure webhook for automated triggers
# Go to: Repository → Webhooks → Add webhook
WEBHOOK_URL="https://example.com/webhook"
curl -X POST https://hub.docker.com/api/content/v1/repositories/USERNAME/myapp/webhooks \
  -H "Authorization: Bearer $DOCKERHUB_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"name\":\"CI Trigger\",\"webhook_url\":\"$WEBHOOK_URL\"}"

期待結果: 読み取り・書き込み権限を持つDocker Hubアクセストークンが作成されます。マルチアーキテクチャサポートでイメージが正常にプッシュされます。脆弱性スキャンが自動実行されます(有効な場合)。READMEがGitHubから同期されます。イメージプッシュ時にWebhookがトリガーされます。

失敗時: レート制限エラーの場合、Proプランへのアップグレードまたはプルスルーキャッシュの実装を検討します。スキャン失敗の場合、プランにスキャンが含まれることを確認します(無料プランでは利用不可)。マルチアーキテクチャビルド失敗の場合、

docker run --privileged --rm tonistiigi/binfmt --install all
でQEMUがインストールされていることを確認します。Webhook失敗の場合、エンドポイントが公開アクセス可能で200 OKを返すことを確認します。

ステップ3: Harborセルフホステッドレジストリのデプロイ

エンタープライズレジストリとしてRBACとレプリケーション機能を持つHarborをHelmでインストールします。

# Add Harbor Helm repository
helm repo add harbor https://helm.gopharbor.io
helm repo update

# Create namespace
kubectl create namespace harbor

# Create values file
cat > harbor-values.yaml <<EOF
expose:
  type: ingress
  tls:
    enabled: true
    certSource: secret
    secret:
      secretName: harbor-tls
  ingress:
    hosts:
      core: harbor.example.com
    className: nginx
    annotations:
      cert-manager.io/cluster-issuer: letsencrypt-prod

externalURL: https://harbor.example.com

persistence:
  enabled: true
  persistentVolumeClaim:
    registry:
      size: 200Gi
      storageClass: gp3
    database:
      size: 10Gi
      storageClass: gp3

harborAdminPassword: "ChangeMe123!"

database:
  type: internal  # Use external: postgres for production

redis:
  type: internal  # Use external: redis for production

trivy:
  enabled: true
  skipUpdate: false

notary:
  enabled: true  # Image signing

chartmuseum:
  enabled: true  # Helm chart storage
EOF

# Install Harbor
helm install harbor harbor/harbor \
  --namespace harbor \
  --values harbor-values.yaml \
  --timeout 10m

# Wait for pods to be ready
kubectl get pods -n harbor -w

# Get admin password
kubectl get secret -n harbor harbor-core -o jsonpath='{.data.HARBOR_ADMIN_PASSWORD}' | base64 -d

# Access Harbor UI
echo "Harbor UI: https://harbor.example.com"
echo "Username: admin"

# Login via Docker CLI
docker login harbor.example.com
# Username: admin
# Password: (from above)

# Create project via API
curl -u "admin:$HARBOR_PASSWORD" -X POST \
  https://harbor.example.com/api/v2.0/projects \
  -H "Content-Type: application/json" \
  -d '{
    "project_name": "myapp",
    "public": false,
    "metadata": {
      "auto_scan": "true",
      "severity": "high",
      "enable_content_trust": "true"
    }
  }'

# Tag and push to Harbor
docker tag myapp:latest harbor.example.com/myapp/app:latest
docker push harbor.example.com/myapp/app:latest

# Configure robot account for CI/CD
# UI: Administration → Robot Accounts → New Robot Account
# Permissions: Pull, Push to specific projects

# Use robot account in CI/CD
docker login harbor.example.com -u 'robot$myapp-ci' -p "$ROBOT_TOKEN"

期待結果: HarborがPostgreSQLとRedisを備えたKubernetesにデプロイされます。IngressがTLSで設定されます。管理UIがアクセス可能です。脆弱性スキャンが有効なプロジェクトが作成されます。ロボットアカウントがCI/CD認証を提供します。Trivyがプッシュ時にイメージをスキャンします。

失敗時: データベース接続エラーの場合、

kubectl logs -n harbor harbor-database-0
でPostgreSQLポッドのログを確認します。Ingressの問題の場合、DNSがLoadBalancerを指しているかcert-managerが証明書を発行しているか確認します。Trivyの失敗の場合、脆弱性データベースが正常にダウンロードされているか確認します。ストレージの問題の場合、
kubectl get pvc -n harbor
でPVCがバインドされているか確認します。

ステップ4: イメージタグ戦略と保持ポリシーの実装

セマンティックバージョニング、イミュータブルタグ、自動クリーンアップを設定します。

# Tagging best practices
# 1. Semantic versioning
docker tag myapp:latest harbor.example.com/myapp/app:v1.2.3
docker tag myapp:latest harbor.example.com/myapp/app:v1.2
docker tag myapp:latest harbor.example.com/myapp/app:v1
docker tag myapp:latest harbor.example.com/myapp/app:latest
# ... (see EXAMPLES.md for complete configuration)

期待結果: イメージがセマンティックバージョン、コミットSHA、環境ラベルでタグ付けされます。保持ポリシーが古いイメージを年齢、プルアクティビティ、またはカウント制限に基づいて自動クリーンアップします。本番タグ(v*パターン)が開発ブランチより長く保持されます。タグなしイメージがストレージ節約のために削除されます。

失敗時: 保持がトリガーされない場合、cronスケジュール構文とHarborタイムゾーン設定を確認します。本番イメージが誤って削除された場合、HarborタグイミュータビリティルールでイミュータブルタグをImplementします。ストレージが依然として増加する場合、アーティファクト保持にHelmチャートやその他のOCIアーティファクトが含まれているか確認します。ポリシーの競合の場合、保持ルールが

or
アルゴリズムを使用し互いに矛盾しないことを確認します。

ステップ5: KubernetesイメージプルシークレットのConfiguration

Kubernetesクラスター向けレジストリ認証をセットアップします。

# Create Docker registry secret
kubectl create secret docker-registry ghcr-secret \
  --docker-server=ghcr.io \
  --docker-username=USERNAME \
  --docker-password=$GITHUB_TOKEN \
  --docker-email=user@example.com \
# ... (see EXAMPLES.md for complete configuration)

期待結果: ターゲットnamespaceにイメージプルシークレットが作成されます。PodがプライベートレジストリからイメージをプルするWay。ServiceAccountがimagePullSecretsを含みます。ImagePullBackOffエラーがありません。

失敗時: 認証エラーの場合、

docker login
で手動認証情報を確認します。シークレットが見つからない場合、namespaceがPodのnamespaceに一致するか確認します。まだ失敗する場合、
kubectl get secret ghcr-secret -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | jq
でシークレットをデコードしJSON構造を確認します。トークンの有効期限が切れた場合、認証情報をローテーションしシークレットを更新します。

ステップ6: 脆弱性スキャンとイメージ署名の有効化

イメージの出所のためのTrivyスキャンとCosignを統合します。

# Install Trivy CLI
wget https://github.com/aquasecurity/trivy/releases/latest/download/trivy_0.47.0_Linux-64bit.tar.gz
tar zxvf trivy_0.47.0_Linux-64bit.tar.gz
sudo mv trivy /usr/local/bin/

# Scan local image
# ... (see EXAMPLES.md for complete configuration)

期待結果: Trivyスキャンが重大度評価付きの脆弱性を検出します。SARIF結果がGitHubセキュリティタブにアップロードされます。クリティカルな脆弱性がCI/CDビルドを失敗させます。Cosignがキーペアまたはキーレス(Fulcio)でイメージに署名します。署名済みイメージの検証が成功します。KyvernoがKubernetesで未署名イメージをブロックします。

失敗時: Trivyデータベースダウンロード失敗の場合、

trivy image --download-db-only
を実行します。誤検知の場合、CVE IDと理由を含む
.trivyignore
ファイルを作成します。Cosign署名失敗の場合、イメージダイジェストが変わっていないことを確認します(署名は特定のダイジェストに適用され、タグではありません)。Kyvernoポリシー失敗の場合、イメージ参照パターンが実際のイメージ名と一致するか確認します。キーレス署名の場合、OIDCトークンに十分な権限があることを確認します。

バリデーション

  • Docker CLIログインでレジストリにアクセス可能
  • 適切な認証でイメージがプッシュ・プル可能
  • マルチアーキテクチャイメージがビルドされマニフェストが作成済み
  • イメージプッシュ時に脆弱性スキャンが自動実行
  • 保持ポリシーがスケジュールで古いイメージをクリーンアップ
  • KubernetesクラスターがimagePullSecrets経由でイメージをプル可能
  • デプロイ前にイメージ署名が検証済み
  • イメージ更新時にWebhook通知がトリガー
  • レジストリUIがスキャン結果とアーティファクトメタデータを表示

よくある落とし穴

  • デフォルトで公開イメージ: GitHubパッケージはデフォルトでプライベート、Docker Hubはデフォルトで公開。セキュリティ要件に一致する可視性設定を確認してください。

  • トークンの有効期限: 個人アクセストークンが有効期限切れになり、CI/CDが壊れます。自動化には有効期限なしのトークンを使用するか、ローテーションを実装してください。

  • タグなしイメージの蓄積: ビルドプロセスがストレージを消費するタグなしイメージを作成します。タグなしアーティファクトの自動クリーンアップを有効にしてください。

  • マルチアーキテクチャサポートなし: amd64のみをビルドし、ARMインスタンスで失敗します。クロスプラットフォームビルドに

    --platform
    フラグ付きの
    docker buildx
    を使用してください。

  • レート制限保護なし: 無料のDocker Hubアカウントは100プル/6時間に制限されています。プルスルーキャッシュを実装するかプランをアップグレードしてください。

  • ミュータブルタグ:

    latest
    タグの上書きが再現性を損ないます。本番には(コミットSHA、セマンティックバージョンの)イミュータブルタグを使用してください。

  • 非セキュアなレジストリ通信: TLSなしのセルフホステッドレジストリ。有効な証明書を持つHTTPSを常に使用してください。

  • アクセス制御なし: チーム間で単一の認証情報を共有しています。プロジェクト固有のロボットアカウントによるRBACを実装してください。

関連スキル

  • create-r-dockerfile
    - レジストリ向けコンテナイメージのビルド
  • optimize-docker-build-cache
    - レジストリプッシュ向け効率的なイメージビルド
  • build-ci-cd-pipeline
    - CI/CDでの自動レジストリプッシュ
  • deploy-to-kubernetes
    - レジストリからのイメージプル
  • implement-gitops-workflow
    - レジストリ間のイメージプロモーション