イメージ管理における「成長の痛み」
アプリケーションの構築を始めたばかりの段階では、Dockerイメージの管理は後回しにされがちです。多くのチームは、パブリックリポジトリにイメージをプッシュしたり、単一のDocker Hubアカウントを共有したりすることから始めます。開発者が2人で、マイクロサービスが3つ程度であればこれでも機能しますが、規模が大きくなるとすぐに破綻します。開発、ステージング、本番の各環境にまたがる50ものマイクロサービスを扱うようになると、そのような場当たり的なアプローチは重大なセキュリティリスクとなります。
昨年、私のチームは壁にぶつかりました。Docker Hubの「6時間につき200回」というプルレート制限によって、CI/CDパイプラインが頻繁に停止してしまったのです。さらに悪いことに、私たちは「盲目」な状態で運用していました。ベースイメージに重大な脆弱性が含まれているかどうかを知る術がなかったのです。また、独自のコードをパブリッククラウドのレジストリからプルすることは、コンプライアンス担当者にとっても好ましいことではありませんでした。私たちは、自社ネットワーク内に、コンテナのための安全で高性能な「保管庫」を必要としていました。
そこで私たちは、セキュリティを最優先事項として設計されたオープンソースのリポジトリであるHarborに移行しました。高トラフィックの本番環境で1日100回以上のビルドを半年間回し続けた結果、その安定性と速度、およびデータに対する完全な所有権が得られるというメリットを実感しています。
なぜHarborが選ばれるのか
AWS ECRやGoogle Artifact Registryのようなクラウドネイティブなソリューションも便利ですが、Harborはクラウドプロバイダーには真似できないレベルの制御を提供します。単なるストレージバケットではなく、フル機能の管理プラットフォームなのです。
きめ細やかなアクセス制御
Harborはイメージをプロジェクト単位で整理するため、権限管理が非常にシンプルです。私は、CI/CDボットにはプッシュ/プル権限を、開発者には本番環境へのプル権限のみを付与するように設定しました。開発用プロジェクトについては、開発者がフルコントロール可能です。KeycloakとOIDC経由で直接連携できるため、別途ユーザーデータベースを管理する必要もありません。
Trivyによるセキュリティの自動化
セキュリティ対策を、手動で行うべきではありません。HarborはTrivyスキャナーを使用して、イメージの全レイヤーをスキャンし、既知のCVE(脆弱性)を特定します。私たちは「イメージに一つでも『致命的(Critical)』な脆弱性がある場合、Harborがプルをブロックする」という厳格なルールを設定しました。これにより、ゼロデイ脆弱性がKubernetesクラスタに紛れ込むのを未然に防いでいます。
スマートな保持ポリシーと同期
ストレージコストは無視できません。ディスク容量を節約するため、14日以上経過した開発用イメージを自動削除するポリシーを設定しました。一方で、本番用のタグは無期限に保持します。複数のデータセンターを運用している場合、Harborはイメージをそれらの間で複製できるため、各地域のクラスタで低レイテンシのプルを実現できます。
実践的な導入手順
Docker Composeを扱ったことがあれば、Harborのセットアップは馴染みやすいでしょう。本番環境では、小規模なインスタンスは避け、少なくとも8GBのRAMと、イメージレイヤー用の高速なSSDを備えた専用のVMを使用してください。
1. 環境の準備
サーバーにDockerとDocker Composeがインストールされていることを確認してください。リソースを惜しまないでください。Harborは、ロギングやデータベース管理のために複数のサイドカーコンテナを実行します。
# バージョンの確認
docker --version
docker-compose --version
2. 取得と設定
最新の安定版をダウンロードします。現在は、安定性とUIが向上したv2.10.0を使用しています。
wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-online-installer-v2.10.0.tgz
tar xvzf harbor-online-installer-v2.10.0.tgz
cd harbor
主な作業はharbor.ymlの編集です。hostnameを正しく設定しないと、Dockerクライアントが接続に失敗します。HTTPでの運用は考えないでください。最新のDockerバージョンでは、特別な回避策を講じない限り接続が拒否されます。
cp harbor.yml.tmpl harbor.yml
vi harbor.yml
証明書が適切に配置されていることを確認してください。本番環境のドメインには、Let’s Encryptを使用するのが最も簡単な方法です。
# harbor.yml の基本設定
hostname: harbor.example.com
https:
port: 443
certificate: /etc/letsencrypt/live/harbor.example.com/fullchain.pem
private_key: /etc/letsencrypt/live/harbor.example.com/privkey.pem
harbor_admin_password: ここに強力なパスワードを設定
3. インストールの実行
インストーラーを実行します。脆弱性スキャンのためのTrivyと、改ざん防止のためにイメージに署名したい場合はNotaryを必ず含めてください。
sudo ./install.sh --with-trivy --with-notary
4. パイプラインへの組み込み
Harborが稼働したら、フローを自動化する必要があります。私たちのGitLab CI設定では、個々の開発者ログインではなく、サービスアカウントを使用しています。これにより資格情報の安全性が保たれ、ログもクリーンになります。
以下は、標準的なビルドおよびプッシュジョブのスニペットです:
build_and_push:
stage: build
script:
- echo "$REGISTRY_PASSWORD" | docker login $REGISTRY_URL -u "$REGISTRY_USER" --password-stdin
- docker build -t $REGISTRY_URL/core/api:$CI_COMMIT_SHORT_SHA .
- docker push $REGISTRY_URL/core/api:$CI_COMMIT_SHORT_SHA
- docker tag $REGISTRY_URL/core/api:$CI_COMMIT_SHORT_SHA $REGISTRY_URL/core/api:latest
- docker push $REGISTRY_URL/core/api:latest
5. 「Scan on Push」によるセーフティネット
プロジェクト設定で「Scan on Push」をすぐに有効にしましょう。これにより、イメージがプッシュされた瞬間にHarborがスキャンを強制します。Trivyが重大なバグを見つけた場合、セキュリティチームにアラートが飛び、デプロイがサーバーに到達する前に停止させることができます。これは、決して眠らない自動の門番です。
最後に
Harborへの移行は、今年私たちが行ったインフラ改善の中で最高のものでした。外部のレート制限への依存をなくし、プロフェッショナルグレードのセキュリティ体制を構築できました。証明書やストレージの管理には多少の手間がかかりますが、それによって得られる安心感は、設定にかかる時間の何倍もの価値があります。10以上のマイクロサービスを管理しているなら、パブリックリポジトリに頼るリスクを冒すのはやめましょう。プライベートレジストリは、成熟したDevOps文化の基盤です。

