mcpField
C
container-security

container-security

github.com/julianobarbosaセキュリティ1462 回インストール3 日前に更新
リポジトリ

container-security について

container-securityは、Azure Container Registryでコンテナイメージを構築するチーム向けの実践的なスキルです。ベースイメージのインポート、ビルド、Trivyスキャン、検出事項の分析、Dockerfileの強化、再ビルドと検証の流れを説明します。

主な機能

  1. 01ベースイメージのACRへのインポート
  2. 02ACRを使ったイメージのビルド
  3. 03TrivyによるイメージとDockerfileのスキャン
  4. 04CVEの分類と修正方法の検討
  5. 05Dockerfile設定の強化
  6. 06イメージの再ビルドと安全性検証

活用シーン

  1. 01ACRクラウドビルドでのDocker Hubレート制限の回避
  2. 02コンテナイメージの脆弱性の確認と優先順位付け
  3. 03SSHアクセスとコンテナ実行権限の強化
  4. 04イメージ再ビルド後のセキュリティ変更の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/julianobarbosa/claude-code-skills --skill container-security

インストール後、Claude Code で/container-securityを入力して読み込まれたか確認します。

同梱ファイルevals/evals.json

詳細

コンテナーイメージのセキュリティ

コンテナーイメージを保護するための完全なワークフローです。スキャン、分析、強化、検証を行います。

ワークフローの概要

Import base image to ACR → Build → Scan with Trivy → Analyze CVEs → Harden Dockerfile → Rebuild → Re-scan → Verify

1. ベースイメージを ACR にインポートする

ベースイメージをプライベート ACR にインポートして、Docker Hub のレート制限を回避します。Azure のインフラストラクチャが代わりにイメージを取得するため、Docker Hub の認証は必要ありません。

# Import a public image into ACR
az acr import --name <registry> \
  --source docker.io/<image>:<tag> \
  --image <local-path>/<image>:<tag>

# Example: import code-server
az acr import --name example-app \
  --source docker.io/codercom/code-server:4.107.1 \
  --image addons/code-server:4.107.1

# Verify
az acr repository show --name <registry> --repository <local-path>/<image>

次に、Dockerfile の FROM を更新して ACR 内のイメージを参照します。

# Before (hits Docker Hub rate limits in ACR cloud builds)
FROM codercom/code-server:latest

# After (pulls from local ACR — no rate limit)
FROM example-app.azurecr.io/addons/code-server:4.107.1

重要:ACR クラウドビルド(az acr build)は、Docker Hub に対して認証されません。Docker Hub を参照する FROM は、いずれレート制限に達します。必ず先にインポートしてください。

2. ACR でビルドする

az acr build --registry <registry> --image <repo>:<tag> -f Dockerfile .

ACR ビルダーの制限 — 以下の Docker 機能はサポートされていません。

  • COPY <<'EOF' のヒアドキュメント構文(BuildKit 専用) — 代わりに RUN printf または RUN cat を使用してください
  • マルチプラットフォームビルドには --platform フラグが必要です
  • BuildKit 固有の RUN --mount ディレクティブ

3. Trivy でスキャンする

オプション A:ACR Task 経由の Trivy(CI に推奨)

まず、Trivy 自体を ACR にインポートします(1 回のみ)。

az acr import --name <registry> \
  --source docker.io/aquasec/trivy:latest \
  --image tools/trivy:latest

次にスキャンします。

# Table format for human review
az acr run --registry <registry> \
  --cmd "<registry>.azurecr.io/tools/trivy:latest image \
    --severity HIGH,CRITICAL \
    <registry>.azurecr.io/<image>:<tag>" /dev/null

# JSON format for programmatic analysis
az acr run --registry <registry> \
  --cmd "<registry>.azurecr.io/tools/trivy:latest image \
    --severity HIGH,CRITICAL --format json \
    <registry>.azurecr.io/<image>:<tag>" /dev/null
オプション B:ローカルで Trivy を実行する(Docker デーモンが必要)
az acr login --name <registry>
trivy image --severity HIGH,CRITICAL <registry>.azurecr.io/<image>:<tag>
オプション C:ローカルの Dockerfile を Trivy でスキャンする(ビルド不要)
trivy config --severity HIGH,CRITICAL,MEDIUM Dockerfile

4. CVE の検出結果を分析する

CRITICAL と HIGH の検出結果をすべて分類します。

カテゴリー対応例
こちらで修正可能Dockerfile で新しいバージョンを固定する古い Go 標準ライブラリでビルドされたツールバイナリ
上流で修正可能追跡、記録し、再確認するベースイメージに脆弱性のある内部依存関係が含まれている
OS レベル、パッチ適用待ち記録し、Debian/Ubuntu のトラッカーを監視するlibsqlite3、openssl
will_not_fixリスクを受け入れるか、代替パッケージを探すDebian の zlib1g

JSON 出力から CRITICAL の概要を抽出します。

import json
data = json.load(open('trivy-results.json'))
for result in data.get('Results', []):
    for v in result.get('Vulnerabilities', []):
        if v.get('Severity') == 'CRITICAL':
            print(f"{v['VulnerabilityID']} | {v['PkgName']} {v.get('InstalledVersion','')} | fix: {v.get('FixedVersion','')} | {v.get('Status','')}")

5. Dockerfile の強化チェックリスト

バージョンの固定(再現性に関する CVE を排除)
# Bad — unpinned, non-reproducible, may pull vulnerable versions
FROM image:latest
RUN curl .../releases/latest/download/tool | bash

# Good — pinned, reproducible, auditable
FROM registry.azurecr.io/addons/image:4.107.1

ARG TOOL_VERSION=v1.2.3
RUN curl -fsSL "https://github.com/org/tool/releases/download/${TOOL_VERSION}/tool_linux_amd64.tar.gz" \
    | tar xz -C /usr/local/bin tool

バージョン変数には ARG を使用します。これにより、更新を 1 行の変更で行え、docker history からも確認できます。

SSH の強化
# Disable password auth, enable key-based only
RUN mkdir -p /run/sshd && \
    sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config && \
    sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && \
    echo "AllowUsers <user>" >> /etc/ssh/sshd_config && \
    ssh-keygen -A && \
    mkdir -p /home/<user>/.ssh && \
    chmod 700 /home/<user>/.ssh && \
    chown <user>:<user> /home/<user>/.ssh
非 root での実行
# Start privileged services as root, then drop privileges
RUN printf '#!/bin/bash\nset -e\n/usr/sbin/sshd\nexec su - <user> -c "<main-process>"\n' \
    > /usr/local/bin/entrypoint.sh && \
    chmod +x /usr/local/bin/entrypoint.sh

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

特権サービスが不要な場合は、次のようにするだけです。

USER <non-root-user>
ENTRYPOINT ["<main-process>"]
その他の強化
  • レイヤーを最小限にする:関連する RUN コマンドをまとめる
  • apt キャッシュを削除する:常に && rm -rf /var/lib/apt/lists/* で終える
  • イメージにシークレットを含めない:実行時に注入する(環境変数、マウントしたシークレット)
  • ダウンロードを検証する:可能な場合はバイナリのチェックサムまたは GPG を検証する
  • 読み取り専用ファイルシステム:可能な場合は実行時に --read-only を追加する

6. 再ビルドして再スキャンする

強化後は、修正を検証するため、必ず再ビルドして再スキャンします。

# Rebuild with new tag
az acr build --registry <registry> --image <repo>:<new-tag> -f Dockerfile .

# Re-scan
az acr run --registry <registry> \
  --cmd "<registry>.azurecr.io/tools/trivy:latest image \
    --severity HIGH,CRITICAL \
    <registry>.azurecr.io/<repo>:<new-tag>" /dev/null

# Compare CRITICAL counts: before vs after

7. 検証チェックリスト

セキュリティサイクルを完了したら、次の項目を確認します。

  • az acr repository show — ベースイメージが ACR に存在する
  • az acr build — レート制限エラーなしで完了する
  • Trivy スキャン — CRITICAL の件数が減っている(残る上流の CVE を記録する)
  • az acr repository show — 最終イメージが ACR に存在する
  • Dockerfile でバージョンが固定されている(ツールに :latest を使用していない)
  • SSH が鍵のみの認証に設定されている(該当する場合)
  • コンテナーが非 root ユーザーで実行される
  • イメージのレイヤーにシークレットが埋め込まれていない

よくあるパターン

レート制限からの復旧

az acr import でもレート制限に達した場合(バーストインポート時に発生します)、15 分待つか、認証済みの Docker Hub アカウントを使用します。

az acr import --name <registry> \
  --source docker.io/<image>:<tag> \
  --image <local-path>/<image>:<tag> \
  --username <dockerhub-user> --password <dockerhub-token>
バージョンを固定した複数ツール対応の Dockerfile
ARG K9S_VERSION=v0.50.18
ARG ARGOCD_VERSION=v3.3.3
ARG YQ_VERSION=v4.52.4
ARG KUSTOMIZE_VERSION=v5.8.0

RUN curl -fsSL "https://github.com/derailed/k9s/releases/download/${K9S_VERSION}/k9s_Linux_amd64.tar.gz" | tar xz -C /usr/local/bin k9s
RUN curl -sSL -o /usr/local/bin/argocd "https://github.com/argoproj/argo-cd/releases/download/${ARGOCD_VERSION}/argocd-linux-amd64" && chmod +x /usr/local/bin/argocd
RUN curl -fsSL "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64" -o /usr/local/bin/yq && chmod +x /usr/local/bin/yq
RUN curl -fsSL "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2F${KUSTOMIZE_VERSION}/kustomize_${KUSTOMIZE_VERSION}_linux_amd64.tar.gz" | tar xz -C /usr/local/bin kustomize

注意点

  • RUN apt-get upgradeではTrivyのCVEデータベースは更新されず、インストール済みパッケージのみが更新されます: Trivyはパッケージのバージョンを独自のデータベースと照合するため、再ビルド後もイメージが赤く表示されます。--db-repositoryを使ってスキャナーのデータベースバージョンを固定し、インポートし直したベースから再ビルドしてください。
  • ACRのクラウドビルドはDocker Hubに対して認証されません: FROM docker.io/...は数回のビルドでは機能しますが、その後、匿名ユーザーのレート制限(IPごとに6時間で100回のプル。Azureの送信NATと共有)に達します。必ず先にaz acr importを実行してください。症状として、再試行すると「機能する」断続的なtoomanyrequestsエラーが発生します。
  • COPY <<'EOF'のヒアドキュメントはACRビルダーでは失敗しますが、ローカルでは機能します: ACRはBuildKitではなく、従来のDockerビルドを使用します。ノートPCでは問題なくビルドできるヒアドキュメント構文も、CIではunexpected EOFで失敗します。RUN printfを使うか、コンテキストからCOPYでファイルをステージングしてください。
  • Trivyの--severity HIGH,CRITICALを指定すると、修正可能なMEDIUMの検出結果が隠れます: フィルタリングすると、目に見えるCRITICALよりも容易に対処できる、パッケージレベルのパッチに関する情報が失われます。リリースごとに一度はフィルタリングせずに実行して全体像を把握し、その後、トリアージ用にフィルタリングしてください。
  • 非rootのUSERディレクティブは、マルチステージビルドのCOPY --fromには適用されません: ステージ間でコピーされたファイルは、コピー元ステージのUID/GIDを保持します。root所有のバイナリをコピーした非rootの最終ステージでは、実行時にexecが失敗します。明示的にCOPY --chown=<user>を使ってください。
  • Debianのwill_not_fix CVEは、イメージをアップグレードしても修正されません: will_not_fixとマークされたzlib1gやlibsslなどは、すべてのDebianリリースに含まれています。ベースタグを切り替えても解決せず、解決するにはディストリビューション(distroless、alpine、ubi)を切り替える必要があります。許容するリスクとして記録し、追い続けないでください。

コメント