パッケージとレジストリ
(トップページはこちら) - (アプリケーションのデプロイとリリースを始める)
「また Docker Hub のレート制限に引っかかった」「依存パッケージのダウンロードでビルドが遅い」「どのパイプラインがこのパッケージを公開したのか追跡できない」。こうした課題に直面したことはありませんか。
GitLabのパッケージ管理機能は、これらの問題を根本から解決します。本記事では、パッケージレジストリ、コンテナレジストリ、仮想レジストリ、依存関係プロキシという4つの中核機能を軸に、実践的な活用方法と技術的な仕組みを解説します。
1. なぜGitLabのパッケージ管理なのか
1.1 解決できる3つの課題
課題1: 外部レジストリへの依存とレート制限
Docker Hubは無料プランで6時間あたり100回のプル制限を設けています。CI/CDパイプラインが頻繁に実行される環境では、この制限にすぐ到達します。
課題2: 依存関係のダウンロード時間
外部レジストリから毎回パッケージをダウンロードすると、ネットワーク遅延やレジストリの応答速度がビルド時間に直結します。
課題3: セキュリティとトレーサビリティの欠如
「誰が」「いつ」「どのパイプラインで」パッケージを公開したのか。外部レジストリだけでは、この情報を追跡できません。
1.2 GitLabが提供する解決策
GitLabは、これらの課題に対して以下の機能で応えます。
2. アーキテクチャと使い分け
2.1 4つの機能の位置づけ
GitLabのパッケージ管理機能は、用途に応じて使い分けます。
| 機能 | 主な用途 | キャッシュ | 複数ソース | 対象 |
|---|---|---|---|---|
| パッケージレジストリ | 自社パッケージの公開・管理 | なし | なし | Maven, npm, PyPI, NuGet等 |
| コンテナレジストリ | 自社コンテナイメージの管理 | なし | なし | Docker/OCI イメージ |
| 仮想レジストリ | 複数外部レジストリの統合 | あり | あり(最大20) | Maven(今後拡張予定) |
| 依存関係プロキシ | Docker Hubのキャッシュ | あり | なし | Docker イメージのみ |
2.2 選択基準
自社で開発したパッケージを管理したい
→ パッケージレジストリまたはコンテナレジストリ
外部レジストリのレート制限を回避したい(Docker Hub)
→ 依存関係プロキシ
複数の外部Mavenレジストリを一元管理したい
→ 仮想レジストリ
コンテナイメージに署名を付けて管理したい
→ コンテナレジストリ(Cosign対応)
3. パッケージレジストリ:トレーサビリティの実現
3.1 CI/CDパイプラインとの完全統合
パッケージレジストリの最大の特徴は、GitLab CI/CDとの深い統合です。CI_JOB_TOKENを使用することで、認証情報をハードコードせずにパッケージを公開できます。
# .gitlab-ci.yml
stages:
- build
- test
- publish
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
build:
stage: build
image: maven:3.8-openjdk-17
script:
- mvn clean package
artifacts:
paths:
- target/*.jar
publish:
stage: publish
image: maven:3.8-openjdk-17
script:
- mvn deploy -s ci_settings.xml -DskipTests
only:
- tags
<!-- ci_settings.xml -->
<settings>
<servers>
<server>
<id>gitlab-maven</id>
<configuration>
<httpHeaders>
<property>
<name>Job-Token</name>
<value>${env.CI_JOB_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>
3.2 パッケージのトレーサビリティ
パッケージの詳細ページでは、以下の情報が自動的に記録されます。
- どのパイプラインが公開したか
- どのコミットSHAから生成されたか
- 誰がトリガーしたか
- いつ公開されたか
これにより、問題のあるパッケージが見つかった場合、即座にソースコードまで遡ることができます。
3.3 監査イベント(Premium/Ultimate)
GitLab 18.2以降、パッケージの公開・削除時に監査イベントが作成されます。
# GraphQL APIで監査イベントを有効化
mutation {
updateNamespacePackageSettings(input: {
namespacePath: "my-group",
mavenPackageRequestsForwarding: true,
auditEventsEnabled: true
}) {
packageSettings {
auditEventsEnabled
}
}
}
監査イベントには以下の情報が含まれます。
- イベントタイプ(公開/削除)
- パッケージ名とバージョン
- 実行ユーザー
- タイムスタンプ
- IPアドレス
3.4 柔軟な権限管理
パッケージレジストリの可視性は、リポジトリとは独立して制御できます。
実用例:オープンソースプロジェクトでの活用
- リポジトリ:パブリック(ソースコードは公開)
- パッケージレジストリ:プライベート(ビルド済みパッケージは内部のみ)
または逆に、
- リポジトリ:プライベート(ソースコードは非公開)
- パッケージレジストリ:パブリック(パッケージは誰でも利用可能)
GitLab 15.7以降では、「誰でもパッケージレジストリから取得可能」設定により、認証なしでのパッケージ取得も可能です。
# .gitlab-ci.yml(外部プロジェクトから公開パッケージを利用)
image: maven:3.8-openjdk-17
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
build:
script:
# 認証不要で公開パッケージを取得
- mvn dependency:get -Dartifact=com.example:my-library:1.0.0 -DremoteRepositories=https://gitlab.example.com/api/v4/projects/123/packages/maven
4. コンテナレジストリ:セキュアなイメージ管理
4.1 OCI準拠の意義
GitLab 16.6以降、コンテナレジストリはOCI配布仕様に準拠しています。これにより、以下のメリットがあります。
1. Helmチャートの保存
Helm 3以降、チャートはOCIイメージとして配布できます。GitLabコンテナレジストリに直接保存可能です。
# Helmチャートをコンテナレジストリにプッシュ
helm package ./my-chart
helm push my-chart-1.0.0.tgz oci://registry.gitlab.com/my-group/my-project
2. マルチアーキテクチャイメージのサポート
AMD64とARM64の両方のイメージを同じタグで管理できます。
# .gitlab-ci.yml
build-multiarch:
image: docker:24-dind
services:
- docker:24-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker buildx create --use
- docker buildx build --platform linux/amd64,linux/arm64 -t $CI_REGISTRY_IMAGE:latest --push .
4.2 コンテナイメージ署名とセキュリティ
GitLab 17.1以降、Cosign署名をコンテナイメージに関連付けることができます。
# .gitlab-ci.yml
stages:
- build
- sign
build-image:
stage: build
image: docker:24-dind
services:
- docker:24-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
sign-image:
stage: sign
image:
name: gcr.io/projectsigstore/cosign:v2.2.0
entrypoint: [""]
variables:
COSIGN_EXPERIMENTAL: "1"
script:
- echo "$COSIGN_PRIVATE_KEY" > cosign.key
- cosign sign --key cosign.key --registry-referrers-mode oci-1-1 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
only:
- main
署名されたイメージは、GitLab UIで署名アイコンが表示され、以下の情報を確認できます。
- 署名者
- 署名日時
- 署名アルゴリズム
- 公開鍵フィンガープリント
4.3 プロジェクト移動時の自動対応
GitLab 16.7以降、コンテナリポジトリを含むプロジェクトの名前変更や移転が自動的に処理されます。
従来の問題
プロジェクトをgroup-a/project-xからgroup-b/project-xに移動すると、コンテナイメージのパスが変わり、既存のデプロイメントが壊れる。
GitLabの解決策
プロジェクト移動時に、コンテナレジストリのパスも自動的に更新されます。ただし、パフォーマンス上の理由から、コンテナリポジトリが1,000個以下のプロジェクトに限定されています。
5. 仮想レジストリ:複数ソースの統合管理
5.1 仮想レジストリが解決する課題
企業環境では、複数のMavenレジストリを使用することが一般的です。
- 社内プライベートレジストリ(独自ライブラリ)
- Maven Central(オープンソースライブラリ)
- JFrog Artifactory(サードパーティライブラリ)
- AWS CodeArtifact(クラウド環境用)
開発者は、これらすべてをpom.xmlやsettings.xmlに設定する必要があり、管理が煩雑になります。
5.2 仮想レジストリのアーキテクチャ
5.3 インテリジェントキャッシング
仮想レジストリのキャッシングは、単純なプロキシキャッシュとは異なります。
キャッシュ有効期間の戦略
デフォルト: 24時間
推奨設定(Maven Central): 0時間(無期限)
推奨設定(社内レジストリ): 1時間
Maven Centralは不変性を保証しているため、一度キャッシュしたパッケージは再検証不要です。一方、社内レジストリはSNAPSHOTバージョンが更新される可能性があるため、短い有効期間を設定します。
ネットワーク障害時のフォールバック
仮想レジストリがアップストリームに接続できない場合でも、キャッシュが存在すれば、有効期間外でもそのキャッシュを返します。これにより、外部レジストリの障害時でもビルドが継続できます。
5.4 アップストリーム優先順位の最適化
アップストリームの順序は、パフォーマンスに大きく影響します。
最適化の原則
-
最も頻繁に使用するレジストリを上位に配置
- 社内レジストリ(80%のパッケージ)→ 優先度1
- Maven Central(15%のパッケージ)→ 優先度2
- その他(5%のパッケージ)→ 優先度3
-
地理的に近いレジストリを優先
- 同一リージョンのレジストリ → 優先度高
- 異なるリージョンのレジストリ → 優先度低
-
認証が不要なレジストリを優先
- パブリックレジストリ → 優先度高
- 認証が必要なレジストリ → 優先度低(認証オーバーヘッドを考慮)
5.5 クリーンアップポリシーによるストレージ最適化
GitLab 18.6以降、仮想レジストリにはクリーンアップポリシーが導入されました。
// GraphQL APIでクリーンアップポリシーを設定
{
"cadence": "weekly",
"retentionPeriod": 30
}
設定例
- 頻度: 週次
- 保持期間: 30日間ダウンロードされていないキャッシュを削除
これにより、使用されていない古いパッケージのキャッシュが自動的に削除され、ストレージコストを削減できます。
6. 依存関係プロキシ:Docker Hubレート制限の完全回避
6.1 Docker Hubレート制限の実態
Docker Hubのレート制限は以下の通りです。
| アカウントタイプ | 制限 |
|---|---|
| 匿名ユーザー | 6時間あたり100プル(IPアドレス単位) |
| 無料アカウント | 6時間あたり200プル(ユーザー単位) |
| Pro/Teamアカウント | 無制限 |
CI/CDパイプラインでは、以下のような状況でプルがカウントされます。
# .gitlab-ci.yml
# この設定では、ジョブ実行ごとに3回のプルが発生
image: node:18-alpine # 1回目
services:
- docker:24-dind # 2回目
test:
image: postgres:15 # 3回目
script:
- npm test
1日に50回パイプラインが実行されると、150プルとなり、無料アカウントの制限に到達します。
6.2 依存関係プロキシの動作原理
依存関係プロキシは、HEADリクエストを活用してレート制限を回避します。
重要なポイント
- HEADリクエストはレート制限にカウントされない
- マニフェストが変更されていない限り、キャッシュから返却
-
alpine:latestのような最新タグでも、実際に更新されたときだけプル
6.3 Docker Hub認証の設定
GitLab 17.10以降、Docker Hub認証をサポートしています。これにより、以下のメリットがあります。
- レート制限が200プル/6時間に向上(無料アカウント)
- プライベートイメージへのアクセスが可能
設定方法(UI)
- グループ設定 → パッケージとレジストリ
- 依存関係プロキシセクション
- Docker Hub認証
- Identity: Docker Hubユーザー名
- Secret: Personal Access Token
設定方法(GraphQL API)
mutation {
updateDependencyProxySettings(input: {
enabled: true,
identity: "yamada-taro",
secret: "dckr_pat_xxxxxxxxxxxx",
groupPath: "my-group"
}) {
dependencyProxySetting {
enabled
identity
}
errors
}
}
6.4 CI/CD内での活用
依存関係プロキシは、CI/CD変数を通じて自動的に利用できます。
# .gitlab-ci.yml
# 依存関係プロキシを使用した設定
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/node:18-alpine
services:
- name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:24-dind
alias: docker
variables:
DOCKER_HOST: tcp://docker:2375
test:
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/postgres:15
script:
- npm test
build:
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
Dockerfileでの使用
# Dockerfile
# 依存関係プロキシ経由でベースイメージを取得
FROM gitlab.example.com:443/my-group/dependency_proxy/containers/node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
CMD ["node", "server.js"]
ビルド時には、以下のように認証します。
# .gitlab-ci.yml
build-with-proxy:
image: docker:24-cli
services:
- docker:24-dind
before_script:
- echo "$CI_DEPENDENCY_PROXY_PASSWORD" | docker login $CI_DEPENDENCY_PROXY_SERVER -u $CI_DEPENDENCY_PROXY_USER --password-stdin
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
6.5 レート制限の確認方法
現在のレート制限状況を確認できます。
# .gitlab-ci.yml
check-rate-limit:
stage: .pre
image: alpine:latest
before_script:
- apk add curl jq
script:
- |
TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq --raw-output .token)
curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1 | grep -i RateLimit
allow_failure: true
出力例:
RateLimit-Limit: 200;w=21600
RateLimit-Remaining: 187;w=21600
7. Terraformモジュールレジストリ:Infrastructure as Codeの管理
7.1 Terraformモジュールの課題
Terraformモジュールを管理する際、以下の課題があります。
- モジュールのバージョン管理が煩雑
- 社内モジュールと外部モジュールの混在
- モジュールの変更履歴が追跡できない
7.2 CI/CDテンプレートによる自動公開
GitLabは、Terraformモジュールの公開を自動化するテンプレートを提供しています。
# .gitlab-ci.yml
include:
- template: Terraform-Module.gitlab-ci.yml
variables:
TERRAFORM_MODULE_DIR: ${CI_PROJECT_DIR}
TERRAFORM_MODULE_NAME: ${CI_PROJECT_NAME}
TERRAFORM_MODULE_SYSTEM: aws
TERRAFORM_MODULE_VERSION: ${CI_COMMIT_TAG}
このテンプレートには、以下のジョブが含まれます。
1. fmt(フォーマット検証)
terraform fmt -check -recursive
2. kics-iac-sast(セキュリティスキャン)
Terraformコードの脆弱性をスキャンします。
3. deploy(モジュール公開)
タグがプッシュされたときのみ実行され、モジュールをレジストリに公開します。
7.3 モジュールの参照方法
名前空間レベルからの参照
# main.tf
module "vpc" {
source = "gitlab.example.com/infrastructure/terraform-aws-vpc/aws"
version = "1.2.0"
cidr_block = "10.0.0.0/16"
availability_zones = ["ap-northeast-1a", "ap-northeast-1c"]
}
プロジェクトレベルからの参照
# main.tf
module "vpc" {
source = "https://gitlab.example.com/api/v4/projects/123/packages/terraform/modules/terraform-aws-vpc/aws/1.2.0"
cidr_block = "10.0.0.0/16"
}
7.4 重複モジュールの管理
GitLab 16.8以降、重複するモジュール名の公開を許可できます。
ユースケース:マルチテナント環境
group-a/terraform-aws-vpc (バージョン 1.0.0)
group-b/terraform-aws-vpc (バージョン 2.0.0)
重複を許可することで、各チームが独自のバージョンを管理できます。
設定方法
- グループ設定 → パッケージとレジストリ
- Terraformモジュールの「重複を許可」をオン
- 例外パターンを正規表現で指定(オプション)
例外パターン: ^terraform-aws-.*
→ terraform-aws-で始まるモジュールは重複を許可しない
8. 実践シナリオ:マイクロサービス開発での活用
8.1 構成例
以下のようなマイクロサービスアーキテクチャを想定します。
my-company/
├── shared-libraries/ # 共通ライブラリ(Javaパッケージ)
├── api-gateway/ # APIゲートウェイ(コンテナ)
├── user-service/ # ユーザーサービス(コンテナ)
├── order-service/ # 注文サービス(コンテナ)
└── infrastructure/ # Terraformモジュール
8.2 共通ライブラリの管理
shared-libraries/.gitlab-ci.yml
include:
- template: Maven.gitlab-ci.yml
variables:
MAVEN_CLI_OPTS: "-s ci_settings.xml --batch-mode"
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
stages:
- build
- test
- publish
build:
stage: build
script:
- mvn $MAVEN_CLI_OPTS compile
test:
stage: test
script:
- mvn $MAVEN_CLI_OPTS test
coverage: '/Total.*?([0-9]{1,3})%/'
publish:
stage: publish
script:
- mvn $MAVEN_CLI_OPTS deploy -DskipTests
only:
- tags
artifacts:
reports:
dotenv: build.env
8.3 マイクロサービスでの共通ライブラリ利用
user-service/pom.xml
<project>
<dependencies>
<!-- GitLabパッケージレジストリから共通ライブラリを取得 -->
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>shared-libraries</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>gitlab-maven</id>
<url>https://gitlab.example.com/api/v4/projects/456/packages/maven</url>
</repository>
</repositories>
</project>
user-service/.gitlab-ci.yml
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/maven:3.8-openjdk-17
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
DOCKER_DRIVER: overlay2
stages:
- build
- test
- package
- deploy
build:
stage: build
script:
- mvn clean compile
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .m2/repository
test:
stage: test
script:
- mvn test
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .m2/repository
policy: pull
package:
stage: package
image: docker:24-cli
services:
- name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:24-dind
alias: docker
before_script:
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $CI_REGISTRY_IMAGE:latest
only:
- main
deploy:
stage: deploy
image:
name: bitnami/kubectl:latest
entrypoint: [""]
script:
- kubectl set image deployment/user-service user-service=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n production
only:
- main
when: manual
8.4 インフラストラクチャのコード化
infrastructure/.gitlab-ci.yml
include:
- template: Terraform-Module.gitlab-ci.yml
variables:
TERRAFORM_MODULE_DIR: ${CI_PROJECT_DIR}/modules/vpc
TERRAFORM_MODULE_NAME: terraform-aws-vpc
TERRAFORM_MODULE_SYSTEM: aws
TERRAFORM_MODULE_VERSION: ${CI_COMMIT_TAG}
インフラストラクチャの適用
# production/main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# GitLabのTerraformモジュールレジストリから取得
module "vpc" {
source = "gitlab.example.com/my-company/terraform-aws-vpc/aws"
version = "1.0.0"
cidr_block = "10.0.0.0/16"
availability_zones = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
module "eks" {
source = "gitlab.example.com/my-company/terraform-aws-eks/aws"
version = "2.1.0"
cluster_name = "production-cluster"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnet_ids
}
9. パフォーマンス最適化とベストプラクティス
9.1 キャッシュ戦略
CI/CDキャッシュとの併用
# .gitlab-ci.yml
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
build:
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/maven:3.8-openjdk-17
script:
- mvn clean package
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .m2/repository
- target/
この設定により、以下の3層キャッシュが機能します。
- CI/CDキャッシュ: ブランチごとの依存関係
- 仮想レジストリ/依存関係プロキシ: グループレベルの共有キャッシュ
- ローカルビルド: 開発者のローカル環境
9.2 ネットワーク最適化
同一リージョン内でのレジストリ配置
GitLabインスタンス: ap-northeast-1
仮想レジストリのアップストリーム:
1. 社内レジストリ(ap-northeast-1)
2. AWS CodeArtifact(ap-northeast-1)
3. Maven Central(グローバル)
地理的に近いレジストリを優先することで、ネットワーク遅延を最小化します。
9.3 ストレージ最適化
クリーンアップポリシーの設定
{
"virtualRegistry": {
"cleanupPolicy": {
"cadence": "weekly",
"retentionPeriod": 30
}
},
"containerRegistry": {
"cleanupPolicy": {
"cadence": "daily",
"keepN": 10,
"olderThan": "90d",
"nameRegex": ".*",
"nameRegexKeep": "^(main|production)-.*"
}
}
}
ストレージ使用量の監視
# .gitlab-ci.yml
storage-report:
stage: .post
image: alpine:latest
before_script:
- apk add curl jq
script:
- |
# グループのストレージ使用量を取得
curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" \
"https://gitlab.example.com/api/v4/groups/my-group/storage" | jq
only:
- schedules
10. セキュリティとコンプライアンス
10.1 脆弱性スキャン
コンテナイメージのスキャン
# .gitlab-ci.yml
include:
- template: Security/Container-Scanning.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
container_scanning:
variables:
CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
パッケージの脆弱性スキャン
# .gitlab-ci.yml
dependency_scanning:
variables:
DS_EXCLUDED_PATHS: "spec,test,tests,tmp"
10.2 アクセス制御
最小権限の原則
開発者(Developer):
- パッケージの公開
- コンテナイメージのプッシュ
レポーター(Reporter):
- パッケージの取得
- コンテナイメージのプル
メンテナー(Maintainer):
- パッケージの削除
- レジストリ設定の変更
オーナー(Owner):
- 監査イベントの有効化
- クリーンアップポリシーの設定
10.3 監査ログの活用
監査イベントのクエリ(GraphQL)
query {
group(fullPath: "my-group") {
auditEvents(first: 100, after: "2024-01-01") {
nodes {
id
author {
name
}
entity {
... on Package {
name
version
}
}
action
createdAt
ipAddress
}
}
}
}
11. 移行ガイド:既存環境からの移行
11.1 JFrog ArtifactoryからGitLabへの移行
ステップ1: パッケージのエクスポート
# JFrog CLIを使用してパッケージをエクスポート
jfrog rt download "libs-release-local/*" ./export/
ステップ2: GitLabへのインポート
# GitLab Package Importerを使用
for file in ./export/**/*.jar; do
mvn deploy:deploy-file \
-DgroupId=com.example \
-DartifactId=$(basename $file .jar) \
-Dversion=1.0.0 \
-Dpackaging=jar \
-Dfile=$file \
-DrepositoryId=gitlab-maven \
-Durl=https://gitlab.example.com/api/v4/projects/123/packages/maven
done
ステップ3: 段階的な移行
<!-- pom.xml -->
<repositories>
<!-- 移行期間中は両方を設定 -->
<repository>
<id>artifactory</id>
<url>https://artifactory.example.com/libs-release</url>
</repository>
<repository>
<id>gitlab-maven</id>
<url>https://gitlab.example.com/api/v4/projects/123/packages/maven</url>
</repository>
</repositories>
11.2 Docker HubからGitLabコンテナレジストリへの移行
ステップ1: イメージのリスト取得
# Docker Hubからイメージリストを取得
curl -s "https://hub.docker.com/v2/repositories/mycompany/?page_size=100" | jq -r '.results[].name'
ステップ2: イメージの移行
#!/bin/bash
DOCKER_HUB_ORG="mycompany"
GITLAB_REGISTRY="registry.gitlab.com/my-group"
for image in $(cat image-list.txt); do
# Docker Hubからプル
docker pull $DOCKER_HUB_ORG/$image:latest
# GitLabレジストリにタグ付け
docker tag $DOCKER_HUB_ORG/$image:latest $GITLAB_REGISTRY/$image:latest
# GitLabレジストリにプッシュ
docker push $GITLAB_REGISTRY/$image:latest
done
ステップ3: CI/CDパイプラインの更新
# 移行前
image: mycompany/app:latest
# 移行後
image: ${CI_REGISTRY_IMAGE}:latest
12. トラブルシューティング
12.1 依存関係プロキシの認証エラー
エラー: HTTP Basic: Access Denied
原因: 2要素認証が有効になっている場合、パスワードではなくPersonal Access Tokenが必要です。
解決策:
# .gitlab-ci.yml
variables:
# パスワードではなくPersonal Access Tokenを使用
CI_DEPENDENCY_PROXY_PASSWORD: ${GITLAB_PAT}
12.2 仮想レジストリのキャッシュミス
症状: 同じパッケージを何度もダウンロードしている
原因: キャッシュ有効期間が短すぎる、またはアップストリームの優先順位が最適化されていない
解決策:
mutation {
updateVirtualRegistryUpstream(input: {
id: "gid://gitlab/VirtualRegistries::Packages::Maven::Upstream/1",
cacheValidityHours: 0 # Maven Centralは無期限キャッシュ
}) {
upstream {
cacheValidityHours
}
}
}
12.3 コンテナレジストリの容量不足
症状: insufficient storage エラー
解決策: クリーンアップポリシーの設定
# .gitlab-ci.yml
cleanup-old-images:
stage: .post
image: alpine:latest
before_script:
- apk add curl jq
script:
- |
# 90日以上前のイメージを削除
curl --request DELETE \
--header "PRIVATE-TOKEN: $CI_JOB_TOKEN" \
"https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/registry/repositories/$REPOSITORY_ID/tags?name_regex=.*&older_than=90d"
only:
- schedules
13. まとめ:次のステップ
GitLabのパッケージ管理機能は、以下の価値を提供します。
13.1 定量的な効果
ビルド時間の短縮
- 依存関係プロキシ導入前: 平均5分
- 導入後: 平均2分(60%削減)
コスト削減
- Docker Hub Pro不要(年間$60/ユーザー × 50ユーザー = $3,000削減)
- 外部レジストリのトラフィック削減(月間$500削減)
セキュリティ向上
- 脆弱性検出率: 95%以上
- 監査イベントによる完全なトレーサビリティ
13.2 推奨される導入順序
フェーズ1: 依存関係プロキシ(1週間)
- グループレベルで依存関係プロキシを有効化
- CI/CD変数を更新(
CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIXの使用) - Docker Hubレート制限の監視
フェーズ2: パッケージレジストリ(2週間)
- 共通ライブラリをパッケージレジストリに移行
- CI/CDパイプラインで自動公開を設定
- 監査イベントを有効化
フェーズ3: コンテナレジストリ(2週間)
- コンテナイメージをGitLabレジストリに移行
- Cosign署名の導入
- クリーンアップポリシーの設定
フェーズ4: 仮想レジストリ(3週間)
- アップストリームレジストリの洗い出し
- 仮想レジストリの作成と優先順位設定
- キャッシュ有効期間の最適化
13.3 継続的な改善
月次レビュー
- ストレージ使用量の確認
- キャッシュヒット率の分析
- レート制限の監視
四半期レビュー
- アップストリーム優先順位の見直し
- クリーンアップポリシーの調整
- セキュリティスキャン結果の分析
GitLabのパッケージ管理機能を活用することで、開発チームはインフラストラクチャの管理から解放され、本質的な開発作業に集中できます。まずは依存関係プロキシから始めて、段階的に機能を拡張していくことをお勧めします。