分散した依存関係がもたらす混乱
ある金曜日の夜、たった一つの依存関係が欠けているためにCI/CDパイプラインが失敗し続けるのを眺めて過ごしたことがあります。複雑なことは何もしておらず、ただホットフィックスをプッシュしようとしていただけでした。原因は、公開レジストリ上の小さなライブラリが、作者によって突然削除されたことでした。これは「left-pad」事件として有名なシナリオです。インターネットから直接プルしていたため、ワークフロー全体が壊れてしまいました。ローカルバックアップもなく、コントロールも全くできない状態でした。
これは単なる稀な出来事ではありません。公開レジストリだけに頼るのはギャンブルです。Docker Hubは現在、匿名ユーザーに対して6時間ごとに100回のプルという厳しい制限を課しています。さらに、公開パッケージは侵害されたり、予告なく消えたりする可能性があります。アーティファクトリポジトリを中央管理することは、ローカルのセーフティネット、高速なキャッシュ、そしてチームの独自コードのための安全な保管庫として機能します。
Sonatype Nexusとは一体何か?
Sonatype Nexus Repository Manager (OSS) は、ソフトウェアアーティファクトを保存・整理するための無料ツールです。企業のプライベート版「App Store」のようなものだと考えてください。数十種類のフォーマットをサポートしていますが、多くのチームはDockerイメージ、JavaのJARファイル、JavaScriptパッケージの管理に利用しています。
Proxy、Hosted、Groupリポジトリの理解
Nexusを使いこなすには、3つの主要なリポジトリタイプを理解することから始まります。このロジックこそが、システムの効率性を高める鍵です:
- Proxy Repositories(プロキシリポジトリ): ローカルキャッシュとして機能します。開発者がMaven Centralからパッケージをリクエストすると、Nexusが一度ダウンロードしてコピーを保存します。次にそのパッケージが必要になった人は、ローカルネットワークからギガビット級の速度で直接取得できます。
- Hosted Repositories(ホステッドリポジトリ): 内部コードを保存する場所です。外部に公開すべきではないプライベートライブラリを作成した場合、ここにパブリッシュします。
- Group Repositories(グループリポジトリ): 複数のリポジトリを一つのURLに統合する機能です。ビルドツールは、公開パッケージとプライベートパッケージの両方を見つけるために、一つのエンドポイントだけを参照すれば済みます。
Nexusインスタンスのセットアップ
NexusをDockerコンテナとして実行するのが、最も手っ取り早い開始方法です。ホスト環境を汚さず、将来のアップグレードも簡単になります。
# データ永続化用のボリュームを作成
docker volume create nexus-data
# Nexusコンテナを実行
docker run -d -p 8081:8081 --name nexus -v nexus-data:/nexus-data sonatype/nexus3:latest
サービスの初期化まで約60秒待ち、http://localhost:8081にアクセスします。ログインには初期管理者パスワードが必要です。次のコマンドを実行して取得してください:
docker exec nexus cat /nexus-data/admin.password
Nexusはすぐにパスワードの変更を求めてきます。内部チーム向けには、匿名読み取りアクセス(anonymous read access)を許可することをお勧めします。これにより、CI/CDランナーは複雑な認証情報を管理することなく依存関係をプルでき、一方で書き込みアクセスは厳重に保護したままにできます。
プライベートMavenパッケージのホスティング
Javaのビルドは、何百もの小さなJARファイルをダウンロードする際に遅くなりがちです。NexusをMavenハブとして使用するには、まず通常 ~/.m2/ にある settings.xml ファイルを設定する必要があります。
UIで Maven2 (hosted) リポジトリを作成した後、ローカル設定に以下の認証情報を追加します:
<settings>
<servers>
<server>
<id>nexus-snapshots</id>
<username>admin</username>
<password>your-new-password</password>
</server>
<server>
<id>nexus-releases</id>
<username>admin</username>
<password>your-new-password</password>
</server>
</servers>
</settings>
次に、プロジェクトの pom.xml を更新し、mvn deploy コマンドがNexusインスタンスを向くように設定します:
<distributionManagement>
<repository>
<id>nexus-releases</id>
<url>http://localhost:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>http://localhost:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
NPMインストールの高速化
現代のWebプロジェクトは、巨大な node_modules フォルダを持つことが多いです。Nexusに NPM (proxy) を設定することで、チーム全体の npm install 時間を50%以上短縮できます。ローカル環境をNexusに向けるには、以下を実行します:
npm config set registry http://localhost:8081/repository/npm-all//
マイクロサービス間でプライベートなUIコンポーネントライブラリを共有する必要がある場合は、**NPM (hosted)** リポジトリを使用します。CLI経由でNexusの認証情報を使用してログインできます:
npm login --registry=http://localhost:8081/repository/npm-internal/
プライベートDockerレジストリの運用
NexusはDockerユーザーにとって画期的なツールです。独自のレジストリをホストすることで、Docker Hubのプル制限を回避し、数ギガバイトに及ぶ大きなイメージをローカルネットワーク内に保持できます。これにより、docker pull 操作がほぼ瞬時になります。
Docker (hosted) リポジトリを作成する際は、8082のような固有のポートを割り当ててください。Docker CLIがレジストリAPIと正しく通信するには専用のポートが必要です。ラボ環境でHTTPSを使用していない場合は、ローカルレジストリを信頼するようにDockerに設定します:
# /etc/docker/daemon.json に追加
{
"insecure-registries" : ["localhost:8082"]
}
これで、イメージのタグ付けとプッシュを数秒で行えるようになります:
docker login localhost:8082
docker tag my-app:latest localhost:8082/my-app:v1.0
docker push localhost:8082/my-app:v1.0
重要なメンテナンスのヒント
ストレージは予想以上に早く一杯になります。10人の開発者チームであれば、自動ビルドを通じて1ヶ月で簡単に50GBのアーティファクトが生成されます。必ず Cleanup Policies(クリーンアップポリシー) を設定してください。例えば、30日間ダウンロードされていないDockerイメージやMavenスナップショットを削除するようにNexusを設定します。
/nexus-data ディレクトリのバックアップを忘れないでください。このフォルダには、すべての設定設定と、これまで保存したすべてのアーティファクトが含まれています。コンテナがクラッシュしてこのデータを失うと、すべての依存関係を手動で再アップロードするまで、ビルドパイプライン全体が停止したままになります。
最後に
アーティファクトの中央管理戦略への移行は、成熟したDevOpsパイプラインに向けた大きな一歩です。これにより安定性が向上し、帯域コストが削減され、ソフトウェアサプライチェーンを完全にコントロールできるようになります。Nexusのセットアップは1時間もかかりませんが、ビルドにもたらされる信頼性は、次の重要なデプロイ時に数え切れないほどのトラブルを未然に防いでくれるでしょう。

