GitLabコンテナレジストリの管理

GitLabコンテナレジストリを使えば、全てのプロジェクトがDockerイメージを保存する独自のスペースを持つことができます。

Dockerレジストリについて詳しくはDockerドキュメントをご覧ください。

このドキュメントは管理者向けのガイドです。GitLabコンテナレジストリの使い方はユーザードキュメントをご覧ください。

コンテナレジストリの有効化

コンテナレジストリを有効にする手順は、使用するインストールの種類によって異なります。

Linux パッケージのインストール

Linuxパッケージを使ってGitLabをインストールした場合、コンテナレジストリはデフォルトで利用可能な場合とそうでない場合があります。

コンテナレジストリは自動的に有効化され、GitLabドメイン、ポート5050、組み込みのLet’s Encryptインテグレーションを使っている場合は利用可能です。

そうでない場合は、コンテナレジストリは有効になっていません。有効にするには

コンテナレジストリは、デフォルトでは HTTPS で動作します。HTTP を使用することもできますが、これは推奨されません。これを実装したい場合は、安全でないレジストリのドキュメントを読んでください。

セルフコンパイルによるインストール

GitLab インストールをセルフコンパイルした場合は、次のようになります:

  1. インストールするGitLabのバージョンに対応するイメージを使ってレジストリをデプロイする必要があります(例:registry.gitlab.com/gitlab-org/build/cng/gitlab-container-registry:v3.15.0-gitlab )。
  2. インストールが完了したら、gitlab.yml でレジストリの設定を行います。
  3. lib/support/nginx/registry-ssl にあるNGINX設定ファイルのサンプルを使用し、hostport 、TLS証明書のパスに一致するように編集します。

gitlab.yml の内部は次のとおりです:

registry:
  enabled: true
  host: registry.gitlab.example.com
  port: 5005
  api_url: http://localhost:5000/
  key: config/registry.key
  path: shared/registry
  issuer: gitlab-issuer

どこに:

パラメータ説明
enabled true falseGitLabのレジストリを有効に falseします。falseデフォルトでは false.
hostレジストリが実行され、ユーザーが使用できるホストURL。
port外部のレジストリ・ドメインがリッスンするポート。
api_urlレジストリが公開している内部 API URL。デフォルトはhttp://localhost:5000 です。外部のDockerレジストリを設定する場合を除き、これを変更しないでください。
keyレジストリのrootcertbundle のペアである秘密鍵の場所。token auth設定のドキュメントをお読みください。
pathこれは、レジストリのrootdirectory で指定されているのと同じディレクトリでなければなりません。ストレージ設定のドキュメントを参照ください。このパスは、GitLabユーザー、Webサーバーユーザー、レジストリユーザーが読めるようにする必要があります。詳しくは#configure-storage-for-the-container-registryを参照ください。
issuerこれは、レジストリのissuerで設定したものと同じ値でなければなりません。トークン認証設定のドキュメントをお読みください。

GitLabをソースからインストールした場合、レジストリのinitファイルは同梱されません。したがって、レジストリの設定を変更した場合、GitLabを再起動してもレジストリは再起動されません。その方法についてはアップストリームのドキュメントを読んでください。

最低限レジストリの設定がサービスとしてcontainer_registry 、レルムとしてhttps://gitlab.example.com/jwt/auth

auth:
  token:
    realm: https://gitlab.example.com/jwt/auth
    service: container_registry
    issuer: gitlab-issuer
    rootcertbundle: /root/certs/certbundle
caution
auth が設定されていない場合、ユーザーは認証なしでDockerイメージを引き出すことができます。

コンテナレジストリドメイン設定

レジストリの外部ドメインは、以下のいずれかの方法で設定できます:

コンテナレジストリにはTLS証明書が必要なため、コストがかかる場合があります。

コンテナレジストリを初めて設定する前に、この点を考慮してください。

既存のGitLabドメインでコンテナレジストリを設定します。

コンテナレジストリが既存のGitLabドメインを使用するように設定されている場合、ポート上でコンテナレジストリを公開することができます。この方法では、既存のGitLab TLS証明書を再利用することができます。

GitLabドメインがhttps://gitlab.example.com 、内部へのポートが5050 、コンテナレジストリを設定する場合:

  • Linux パッケージのインストールを使用している場合は、gitlab.rb を編集してください。
  • セルフコンパイルのインストールを使用している場合は、gitlab.yml を編集してください。

レジストリがリッスンするポート ( デフォルトでは5000 ) とは異なるポートを選択してください。

note
ホストとコンテナのファイアウォールルールは、gitlab_rails['registry_port'] (デフォルトでは5000)に記載されているポートではなく、registry_external_url に記載されているポートからのトラフィックを許可するように設定する必要があります。
Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb には、レジストリの URL と、GitLab が使用している既存の TLS 証明書と鍵へのパスを記述してください:

    registry_external_url 'https://gitlab.example.com:5050'
    

    registry_external_url は既存の GitLab URL の下で HTTPS をリッスンしていますが、ポートは異なります。

    TLS 証明書が/etc/gitlab/ssl/gitlab.example.com.crt になく、鍵が/etc/gitlab/ssl/gitlab.example.com.key にない場合は、以下の行のコメントを外してください:

    registry_nginx['ssl_certificate'] = "/path/to/certificate.pem"
    registry_nginx['ssl_certificate_key'] = "/path/to/certificate.key"
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

  3. を使って検証します:

    openssl s_client -showcerts -servername gitlab.example.com -connect gitlab.example.com:5050 > cacert.pem
    

証明書プロバイダがCAバンドル証明書を提供する場合は、それをTLS証明書ファイルに追加します。

管理者は、コンテナレジストリが5678 のような任意のポートをリッスンすることを望むかもしれません。しかし、レジストリとアプリケーションサーバーは、ポート80443 のみをリッスンする AWS アプリケーションロードバランサーの背後にあります。管理者はregistry_external_urlのポート番号を削除することができ、HTTP または HTTPS が想定されます。そして、ロードバランサーをポート80 または443 から任意のポートにレジストリにマップするルールが適用されます。ユーザがコンテナレジストリのdocker login の例に依存している場合、これはインポートです。以下はその例です:

registry_external_url 'https://registry-gitlab.example.com'
registry_nginx['redirect_http_to_https'] = true
registry_nginx['listen_port'] = 5678
Self-compiled (source)
  1. /home/git/gitlab/config/gitlab.yml を開き、registry エントリを見つけ、以下の設定で構成します:

    registry:
      enabled: true
      host: gitlab.example.com
      port: 5050
    
  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。
  3. NGINXにも関連する変更を加えます(ドメイン、ポート、TLS証明書のパス)。

これで、ユーザーは GitLab の認証情報を使ってコンテナレジストリにサインインできるようになります:

docker login gitlab.example.com:5050

コンテナレジストリの独自ドメイン設定

レジストリが独自のドメインを使用するように設定されている場合、その特定のドメイン用のTLS証明書が必要です(例えば、registry.example.com )。既存の GitLab ドメインのサブドメインでホストしている場合は、ワイルドカード証明書が必要になるかもしれません。例えば、*.gitlab.example.comregistry.gitlab.example.com と一致するワイルドカードで、*.example.comとは異なります。

手動で生成されたSSL証明書(こちらで説明)と同様に、LinuxパッケージのインストールではLet’s Encryptによって自動生成された証明書もサポートされています。

コンテナレジストリをhttps://registry.gitlab.example.com でアクセスできるようにするとします。

Linux package (Omnibus)
  1. TLS 証明書と鍵を/etc/gitlab/ssl/registry.gitlab.example.com.crt/etc/gitlab/ssl/registry.gitlab.example.com.key に配置し、それらの権限が正しいことを確認します:

    chmod 600 /etc/gitlab/ssl/registry.gitlab.example.com.*
    
  2. TLS証明書を配置したら、/etc/gitlab/gitlab.rb

    registry_external_url 'https://registry.gitlab.example.com'
    

    registry_external_url はHTTPSでリッスンしています。

  3. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

ワイルドカード証明書を使用している場合は、URLに加えて証明書へのパスを指定する必要があります。この場合、/etc/gitlab/gitlab.rb のようになります:

registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem"
registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key"
Self-compiled (source)
  1. /home/git/gitlab/config/gitlab.yml を開き、registry エントリを見つけ、以下の設定で構成します:

    registry:
      enabled: true
      host: registry.gitlab.example.com
    
  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。
  3. NGINXにも関連する変更を加えます(ドメイン、ポート、TLS証明書のパス)。

これで、ユーザーは GitLab の認証情報を使ってコンテナレジストリにサインインできるようになるはずです:

docker login registry.gitlab.example.com

コンテナレジストリをサイト全体で無効にします。

以下の手順でレジストリを無効化しても、既存のDockerイメージは削除されません。Dockerイメージの削除はレジストリアプリケーション自体で処理されます。

Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb を開き、registry['enable']false に設定します:

    registry['enable'] = false
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)
  1. /home/git/gitlab/config/gitlab.yml を開き、registry エントリを見つけ、enabledfalseに設定します:

    registry:
      enabled: false
    
  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。

新しいプロジェクトのコンテナレジストリをサイト全体で無効にします。

コンテナレジストリを有効にすると、すべての新規プロジェクトで利用できるようになります。この機能を無効にして、プロジェクトのオーナーが自分でコンテナレジストリを有効にするには、以下の手順に従います。

Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb を編集し、以下の行を追加します:

    gitlab_rails['gitlab_default_projects_features_container_registry'] = false
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)
  1. /home/git/gitlab/config/gitlab.yml を開き、default_projects_features エントリを見つけ、container_registryfalseになるように設定します:

    ## Default project features settings
    default_projects_features:
      issues: true
      merge_requests: true
      wiki: true
      snippets: false
      builds: true
      container_registry: false
    
  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。

トークンの持続時間を増やす

GitLabでは、コンテナレジストリのトークンは5分ごとに失効します。トークンの有効期間を長くするには

  1. 左のサイドバーで、Search を選択するか、次のページに進んでください。
  2. Admin Areaを選択します。
  3. 左サイドバーで、Settings > CI/CDを選択します。
  4. コンテナレジストリを展開します。
  5. Authorization token duration (minutes)] で、値を更新します。
  6. 変更を保存を選択します。

コンテナレジストリのストレージ設定

note
この機能をサポートしているストレージバックエンドでは、オブジェクトバージョニングを使用して、バケットに保存されているすべてのオブジェクトの最新バージョンでないものを保存、取得、リストアすることができます。しかし、この場合、ストレージの使用量とコストが高くなる可能性があります。レジストリのオペレーション上、画像のアップロードはまず一時的なパスに保存され、それから最終的な場所に転送されます。S3 や GCS を含むオブジェクトストレージのバックエンドでは、この転送はコピーに続いて削除で行われます。オブジェクトのバージョニングを有効にすると、削除された一時的なアップロードのアーティファクトは非現行バージョンとして保持されるため、ストレージのバケットサイズが大きくなります。非現行バージョンが一定時間後に削除されるようにするには、ストレージプロバイダでオブジェクトライフサイクルポリシーを設定する必要があります。
caution
コンテナレジストリに格納されているファイルやオブジェクトを直接変更しないでください。レジストリ以外がこれらのエントリを書き込んだり削除したりすると、インスタンス全体のデータの一貫性や不安定性の問題が発生し、回復できなくなる可能性があります。

ストレージドライバを設定することで、コンテナレジストリに様々なストレージバックエンドを使用するように設定できます。デフォルトでは、GitLabコンテナレジストリはファイルシステムドライバの設定を使用するように設定されています。

サポートされているドライバは以下の通りです:

ドライバー説明
filesystemローカルファイルシステム上のパスを使用
azureMicrosoft Azure Blob Storage
gcsGoogleクラウドストレージ
s3Amazon Simple Storage Service。正しいS3権限スコープでストレージバケットを設定してください。
swiftOpenStack Swiftオブジェクトストレージ
ossアリユンOSS

ほとんどのS3互換サービス(MinIOなど)はコンテナレジストリで動作するはずですが、AWS S3のサポートのみを保証しています。サードパーティのS3実装の正しさを保証できないため、イシューをデバッグすることはできますが、問題がAWS S3バケットに対して再現可能でない限り、レジストリにパッチを当てることはできません。

個々のドライバの設定オプションについてはDockerレジストリのドキュメントを参照してください。

ファイルシステムを使用

ファイルシステムに画像を保存したい場合は、コンテナレジストリの保存パスを変更することができます。

このパスにアクセスできます:

  • コンテナレジストリデーモンを実行しているユーザー。
  • GitLab を実行しているユーザー。

GitLab、レジストリ、ウェブサーバのすべてのユーザーがこのディレクトリにアクセスできる必要があります。

Linux package (Omnibus)

Linuxパッケージのインストールでイメージが保存されるデフォルトの場所は/var/opt/gitlab/gitlab-rails/shared/registry です。変更するには

  1. /etc/gitlab/gitlab.rb を編集します:

    gitlab_rails['registry_path'] = "/path/to/registry/storage"
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)

セルフコンパイルしたインストールでイメージが保存されるデフォルトの場所は/home/git/gitlab/shared/registry です。変更するには

  1. /home/git/gitlab/config/gitlab.yml を開き、registry エントリーを見つけ、path の設定を変更します:

    registry:
      path: shared/registry
    
  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。

オブジェクトストレージの使用

オブジェクトストレージに画像を保存したい場合は、コンテナレジストリのストレージドライバを変更します。

GitLab でのオブジェクトストレージの使用について、詳しくはこちらをご覧ください。

caution
GitLabはファイルシステムに保存されていないDockerイメージはバックアップしません。必要であれば、オブジェクトストレージプロバイダーでバックアップを有効にしてください。

Linux パッケージインストール用のs3gcs ストレージドライバの設定

以下の設定手順は、s3 およびgcs ストレージドライバ用です。その他のストレージドライバもサポートされています。

Linux パッケージインストール用にs3 ストレージドライバを設定するには:

  1. /etc/gitlab/gitlab.rb を編集します:

    registry['storage'] = {
      's3' => {
        'accesskey' => 's3-access-key',
        'secretkey' => 's3-secret-key-for-access-key',
        'bucket' => 'your-s3-bucket',
        'region' => 'your-s3-region',
        'regionendpoint' => 'your-s3-regionendpoint'
      }
    }
    

    静的な認証情報を使用しないようにするには、IAMロールを使用し、accesskeysecretkey を省略します。IAMプロファイルがDockerによって文書化された権限に従っていることを確認してください。

    registry['storage'] = {
      's3' => {
        'bucket' => 'your-s3-bucket',
        'region' => 'your-s3-region'
      }
    }
    

    AWS S3 VPCエンドポイントで使用する場合は、regionendpoint をVPCエンドポイントのアドレスに設定し、pathstyle をfalseに設定します:

    registry['storage'] = {
      's3' => {
        'accesskey' => 's3-access-key',
        'secretkey' => 's3-secret-key-for-access-key',
        'bucket' => 'your-s3-bucket',
        'region' => 'your-s3-region',
        'regionendpoint' => 'your-s3-vpc-endpoint',
        'pathstyle' => false
      }
    }
    
    • regionendpoint は、MinIOなどのS3互換サービスを設定する場合、またはAWS S3 VPCエンドポイントを使用する場合にのみ必要です。
    • your-s3-bucket は存在するバケツの名前でなければならず、サブディレクトリを含めることはできません。
    • pathstyle bucket_name.host/object の代わりにhost/bucket_name/object 形式のパスを使用するには、true を設定します。AWS S3 の場合は false を設定します。

    S3 APIからの503エラーを避けるために、S3への接続にレート制限を設定することができます。これを行うには、maxrequestspersecondS3 リクエストレート閾値内の数値に設定します:

       registry['storage'] = {
       's3' => {
         'accesskey' => 's3-access-key',
         'secretkey' => 's3-secret-key-for-access-key',
         'bucket' => 'your-s3-bucket',
         'region' => 'your-s3-region',
         'regionendpoint' => 'your-s3-regionendpoint',
         'maxrequestspersecond' => 100
       }
     }
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Linux パッケージインストール用にgcs ストレージドライバを設定するには:

  1. /etc/gitlab/gitlab.rb を編集します:

       registry['storage'] = {
       'gcs' => {
         'bucket' => 'BUCKET_NAME',
         'keyfile' => 'PATH/TO/KEYFILE',
         # If you have the bucket shared with other apps beyond the registry, uncomment the following:
         # 'rootdirectory' => '/gcs/object/name/prefix'
       }
     }
    

    GitLabは全てのパラメータをサポートしています。

  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

セルフコンパイルによるインストール

ストレージドライバの設定は、Dockerレジストリのデプロイ時に作成したレジストリ設定YAMLファイルで行います。

s3 ストレージドライバの例です:

storage:
  s3:
    accesskey: 's3-access-key'                # Not needed if IAM role used
    secretkey: 's3-secret-key-for-access-key' # Not needed if IAM role used
    bucket: 'your-s3-bucket'
    region: 'your-s3-region'
    regionendpoint: 'your-s3-regionendpoint'
  cache:
    blobdescriptor: inmemory
  delete:
    enabled: true

your-s3-bucket は存在するバケツの名前でなければならず、サブディレクトリを含めることはできません。

ダウンタイムなしでオブジェクトストレージにマイグレーション

caution
AWS DataSyncを使用してレジストリデータをS3バケットへ、またはS3バケット間でコピーすると、バケット内に無効なメタデータオブジェクトが作成されます。詳細については、「空の名前を持つタグ」を参照してください。S3バケットへ、またはS3バケット間でデータを移動するには、AWS CLIsync のオペレーションを推奨します。

コンテナレジストリを停止せずにストレージをマイグレーションするには、コンテナレジストリを読み取り専用モードに設定します。大規模インスタンスでは、Container Registryをしばらくの間読み取り専用モードにする必要があるかもしれません。この間、コンテナレジストリからプルすることはできますが、プッシュすることはできません。

  1. オプション:マイグレーションするデータ量を減らすには、ガベージコレクションツールをダウンタイムなしで実行します。
  2. この例では、aws CLI を使用します。CLIを設定したことがない場合は、sudo aws configure を実行して認証情報を設定する必要があります。管理者でないユーザーはコンテナレジストリフォルダにアクセスできない可能性が高いため、必ずsudo を使用してください。クレデンシャルの設定を確認するには、ls を実行してすべてのバケットを一覧表示します。

    sudo aws --endpoint-url https://your-object-storage-backend.com s3 ls
    

    バックエンドに AWS を使用している場合は、--endpoint-url は必要ありません。

  3. aws CLIcp またはsync コマンドなどで、初期データを S3 バケットにコピーします。バケット内部のトップレベルフォルダはdocker フォルダにしてください。

    sudo aws --endpoint-url https://your-object-storage-backend.com s3 sync registry s3://mybucket
    
    note
    データ量が多い場合は、同期オペレーションを並行して行うことでパフォーマンスが向上する可能性があります。
  4. 最後のデータ同期を行うために、コンテナレジストリをread-only モード にし、GitLab を再設定します。
  5. 最初のデータロード以降に行われた変更を S3 バケットに同期し、移行先のバケットに存在するが移行元には存在しないファイルを削除します:

    sudo aws --endpoint-url https://your-object-storage-backend.com s3 sync registry s3://mybucket --delete --dryrun
    

    コマンドが期待通りに実行されることを確認したら、--dryrun フラグを外してコマンドを実行します。

    caution
    この --deleteフラグは、コピー先には存在するがコピー元には存在しないファイルを削除します。ソースと宛先を入れ替えると、レジストリ内のすべてのデータが削除されます。
  6. これら2つのコマンドによって返されるファイルカウントを見て、すべてのコンテナレジストリファイルがオブジェクトストレージにアップロードされたことを確認します:

    sudo find registry -type f | wc -l
    
    sudo aws --endpoint-url https://your-object-storage-backend.com s3 ls s3://mybucket --recursive | wc -l
    

    これらのコマンドの出力は、_uploads ディレクトリとサブディレクトリの内容を除いて一致するはずです。

  7. ストレージにS3バケットを使用するようにレジストリを設定します。
  8. 変更を有効にするには、レジストリをread-write モードに戻し、GitLab を再設定します。

Azure オブジェクトストレージへの移行

GitLab 16.0ではストレージドライバのデフォルト設定が変更される予定です。

caution
ストレージドライバのデフォルト設定はGitLab 16.0で変更される予定です。ストレージドライバはデフォルトのルートディレクトリとして/ 。混乱を避けるために、今すぐ現在の設定にtrimlegacyrootprefix: false 。詳しくはコンテナレジストリ設定ドキュメントをご覧ください。

既存のファイルシステムまたは別のオブジェクトストレージプロバイダーから Azure Object Storage に移行する場合は、標準のルートディレクトリを使用するようにレジストリを設定する必要があります。レジストリ設定の Azure ストレージドライバセクションでtrimlegacyrootprefix: true を設定して構成します。この設定を行わないと、Azure ストレージドライバは、ルートパスの最初のセクションとして/ ではなく// を使用し、マイグレーションしたイメージにアクセスできなくなります。

Linux package (Omnibus)
registry['storage'] = {
  'azure' => {
    'accountname' => 'accountname',
    'accountkey' => 'base64encodedaccountkey',
    'container' => 'containername',
    'rootdirectory' => '/azure/virtual/container',
    'trimlegacyrootprefix' => true
  }
}
Self-compiled (source)
storage:
  azure:
    accountname: accountname
    accountkey: base64encodedaccountkey
    container: containername
    rootdirectory: /azure/virtual/container
    trimlegacyrootprefix: true

デフォルトでは、Azure Storage Driver はcore.windows.net レルムを使用します。azure セクションで、realm に別の値を設定できます(たとえば、Azure Government Cloud の場合は、core.usgovcloudapi.net )。詳細については、Dockerドキュメントを参照してください。

ストレージドライバのリダイレクトを無効にします。

デフォルトでは、リモートバックエンドで設定されたレジストリにアクセスするユーザーは、ストレージドライバのデフォルトバックエンドにリダイレクトされます。例えば、レジストリはs3 ストレージドライバを使って設定することができます。このドライバはGitLabサーバの負荷を軽減するためにリクエストをリモートのS3バケットにリダイレクトします。

しかし、通常公開サーバーにアクセスできない内部ホストで使われるレジストリにとって、この動作は望ましくありません。リダイレクトとプロキシダウンロードを無効にするには、次のようにdisable フラグを true に設定します。これにより、すべてのトラフィックが常にレジストリサービスを経由するようになります。この結果、セキュリティは向上しますが (ストレージのバックエンドが公開されていないため、攻撃されにくくなります)、パフォーマンスは低下します (すべてのトラフィックがサービスを経由してリダイレクトされます)。

Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb を編集します:

    registry['storage'] = {
      's3' => {
        'accesskey' => 's3-access-key',
        'secretkey' => 's3-secret-key-for-access-key',
        'bucket' => 'your-s3-bucket',
        'region' => 'your-s3-region',
        'regionendpoint' => 'your-s3-regionendpoint'
      },
      'redirect' => {
        'disable' => true
      }
    }
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)
  1. レジストリ設定の YAML ファイルにredirect フラグを追加します:

    storage:
      s3:
        accesskey: 'AKIAKIAKI'
        secretkey: 'secret123'
        bucket: 'gitlab-registry-bucket-AKIAKIAKI'
        region: 'your-s3-region'
        regionendpoint: 'your-s3-regionendpoint'
      redirect:
        disable: true
      cache:
        blobdescriptor: inmemory
      delete:
        enabled: true
    
  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。

暗号化されたS3バケット

デフォルトでSSE-S3またはSSE-KMS暗号化が有効になっているS3バケットに対して、AWS KMSでサーバーサイド暗号化を使用できます。カスタマーマスターキー(CMK)とSSE-C暗号化は、リクエストごとに暗号化キーを送信する必要があるため、サポートされていません。

SSE-S3の場合、レジストリ設定でencrypt オプションを有効にする必要があります。この方法はGitLabのインストール方法によって異なります。あなたのインストール方法に合ったこちらの手順に従ってください。

Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb を編集します:

    registry['storage'] = {
      's3' => {
        'accesskey' => 's3-access-key',
        'secretkey' => 's3-secret-key-for-access-key',
        'bucket' => 'your-s3-bucket',
        'region' => 'your-s3-region',
        'regionendpoint' => 'your-s3-regionendpoint',
        'encrypt' => true
      }
    }
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)
  1. レジストリ設定の YAML ファイルを編集します:

    storage:
      s3:
        accesskey: 'AKIAKIAKI'
        secretkey: 'secret123'
        bucket: 'gitlab-registry-bucket-AKIAKIAKI'
        region: 'your-s3-region'
        regionendpoint: 'your-s3-regionendpoint'
        encrypt: true
    
  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。

ストレージの制限

ストレージの制限はありませんので、ユーザーは任意のサイズのDockerイメージを無限にアップロードすることができます。この設定は将来のリリースで設定可能になるはずです。

レジストリ内部ポートの変更

レジストリサーバーは、デフォルトで localhost のポート5000 を待ち受けます。 これは、レジストリサーバーが接続を受け付けるべきアドレスです。以下の例では、レジストリのポートを5010 に設定します。

Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb を開き、registry['registry_http_addr'] を設定します:

    registry['registry_http_addr'] = "localhost:5010"
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)
  1. レジストリ・サーバーの設定ファイルを開き、http:addr の値を編集します:

    http:
      addr: localhost:5010
    
  2. ファイルを保存し、レジストリサーバーを再起動します。

プロジェクトごとのコンテナレジストリの無効化

GitLabインスタンスでレジストリが有効になっているが、プロジェクトでは必要ない場合は、プロジェクトの設定からレジストリを無効にすることができます。

GitLab を認証エンドポイントとして外部コンテナレジストリを使用します。

caution
GitLabでの外部コンテナレジストリの使用はGitLab 15.8で非推奨となり、サポート終了はGitLab 16.0の予定です。GitLabコンテナレジストリの代わりに外部コンテナレジストリを使用する必要がある場合は、フィードバック課題958で使用例を教えてください。

外部のコンテナレジストリを使用する場合、コンテナレジストリに関連するいくつかの機能が使用できなくなったり、固有のリスクが発生したりする可能性があります。

インテグレーションを機能させるには、外部レジストリが GitLab と認証するために JSON Web Token を使用するように設定する必要があります。外部レジストリのランタイム設定には、以下のエントリが必要です:

auth:
  token:
    realm: https://gitlab.example.com/jwt/auth
    service: container_registry
    issuer: gitlab-issuer
    rootcertbundle: /root/certs/certbundle

これらのエントリがないと、レジストリログインはGitLabで認証できません。GitLabはまた、registry.example.com/group/project/image-name:tagregistry.example.com/group/project/my/image-name:tag のようなプロジェクト階層下のネストしたイメージ名を認識せず、registry.example.com/group/project:tagのみを認識します。

Linux パッケージのインストール

GitLab を外部コンテナレジストリの認証エンドポイントとして使うことができます。

  1. /etc/gitlab/gitlab.rb を開き、必要な設定を行います:

    gitlab_rails['registry_enabled'] = true
    gitlab_rails['registry_api_url'] = "https://<external_registry_host>:5000"
    gitlab_rails['registry_issuer'] = "gitlab-issuer"
    
    • gitlab_rails['registry_enabled'] = true はGitLab Container Registryの機能と認証エンドポイントを有効にするために必要です。これを有効にしても、GitLabにバンドルされているコンテナレジストリサービスは起動しません。
    • gitlab_rails['registry_api_url'] = "http://<external_registry_host>:5000" は、レジストリがインストールされているホストに合わせて変更する必要があります。また、内部レジストリがTLSを使用するように設定されている場合は、https を指定する必要があります。詳しくはDockerレジストリのドキュメントをご覧ください。
  2. GitLabと外部コンテナレジストリが安全に通信するためには、証明鍵と鍵のペアが必要です。証明書と鍵のペアを作成し、外部コンテナレジストリに公開証明書 (rootcertbundle) を設定し、GitLabに秘密鍵を設定する必要があります。そのためには、/etc/gitlab/gitlab.rb に以下を追加します:

    # registry['internal_key'] should contain the contents of the custom key
    # file. Line breaks in the key file should be marked using `\n` character
    # Example:
    registry['internal_key'] = "---BEGIN RSA PRIVATE KEY---\nMIIEpQIBAA\n"
       
    # Optionally define a custom file for a Linux package installation to write the contents
    # of registry['internal_key'] to.
    gitlab_rails['registry_key_path'] = "/custom/path/to/registry-key.key"
    

    reconfigure が実行されるたびに、registry_key_path で指定されたファイルにinternal_key で指定された内容が入力されます。ファイルが指定されていない場合、Linuxパッケージのインストールはデフォルトで/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key

  3. GitLab Container Registry ページに表示されるコンテナレジストリ URL を変更するには、以下の設定を行います:

    gitlab_rails['registry_host'] = "registry.gitlab.example.com"
    gitlab_rails['registry_port'] = "5005"
    
  4. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

セルフコンパイルによるインストール

  1. /home/git/gitlab/config/gitlab.yml を開き、registry の設定を編集します:

    ## Container Registry
       
    registry:
      enabled: true
      host: "registry.gitlab.example.com"
      port: "5005"
      api_url: "https://<external_registry_host>:5000"
      path: /var/lib/registry
      key: /path/to/keyfile
      issuer: gitlab-issuer
    

    これらのパラメーターの意味については、こちらをお読みください。

  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。

コンテナレジストリ通知の設定

コンテナレジストリは、レジストリで発生したイベントに応じて Webhook 通知を送信するように設定できます。

コンテナレジストリの通知設定オプションの詳細については、Docker Registry notifications documentation を参照してください。

コンテナレジストリには複数のエンドポイントを設定できます。

Linux package (Omnibus)

Linux パッケージインストール用の通知エンドポイントを設定するには、以下の手順に従います:

  1. /etc/gitlab/gitlab.rb を編集します:

    registry['notifications'] = [
      {
        'name' => 'test_endpoint',
        'url' => 'https://gitlab.example.com/notify',
        'timeout' => '500ms',
        'threshold' => 5,
        'backoff' => '1s',
        'headers' => {
          "Authorization" => ["AUTHORIZATION_EXAMPLE_TOKEN"]
        }
      }
    ]
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)

通知エンドポイントの設定は、Dockerレジストリをデプロイしたときに作成したレジストリ設定YAMLファイルで行います。

使用例:

notifications:
  endpoints:
    - name: alistener
      disabled: false
      url: https://my.listener.com/event
      headers: <http.Header>
      timeout: 500
      threshold: 5
      backoff: 1000

今すぐクリーンアップポリシーを実行

caution
ディストリビューションアーキテクチャを使用しており、Sidekiqが別のノードで実行されている場合、クリーンアップポリシーは機能しません。これを修正するには
  1. 正しいレジストリURLを指すように、Sidekiqノードのgitlab.rb ファイルを設定します。
  2. registry.key ファイルを各Sidekiqノードにコピーします。

詳細については、Sidekiq設定ページを参照してください。

特定のプロジェクトによって使用されるコンテナレジストリのディスク容量を削減するために、管理者はクリーンアップポリシーを設定し、ガベージコレクションを実行することができます。

プロジェクト別レジストリディスク使用量

各プロジェクトのディスク使用量を調べるには、GitLab Railsコンソールで以下を実行します:

projects_and_size = [["project_id", "creator_id", "registry_size_bytes", "project path"]]
# You need to specify the projects that you want to look through. You can get these in any manner.
projects = Project.last(100)

projects.each do |p|
   project_total_size = 0
   container_repositories = p.container_repositories

   container_repositories.each do |c|
       c.tags.each do |t|
          project_total_size = project_total_size + t.total_size unless t.total_size.nil?
       end
   end

   if project_total_size > 0
      projects_and_size << [p.project_id, p.creator.id, project_total_size, p.full_path]
   end
end

# print it as comma separated output
projects_and_size.each do |ps|
   puts "%s,%s,%s,%s" % ps
end

クリーンアップポリシーを実行してイメージタグを削除するには、GitLab Railsコンソールで以下のコマンドを実行します:

# Numeric ID of the project whose container registry should be cleaned up
P = <project_id>

# Numeric ID of a user with Developer, Maintainer, or Owner role for the project
U = <user_id>

# Get required details / objects
user    = User.find_by_id(U)
project = Project.find_by_id(P)
policy  = ContainerExpirationPolicy.find_by(project_id: P)

# Loop through each container repository
project.container_repositories.find_each do |repo|
  puts repo.attributes

  # Start the tag cleanup
  puts Projects::ContainerRepository::CleanupTagsService.new(container_repository: repo, current_user: user, params: policy.attributes.except("created_at", "updated_at")).execute
end

スケジュールでクリーンアップを実行することもできます。

コンテナレジストリのガベージコレクション

note
Amazon S3 Lifecycleなどのオブジェクトストレージプロバイダの保持ポリシーによって、オブジェクトが適切に削除されない場合があります。

コンテナ・レジストリはかなりの量のストレージ・スペースを使用する可能性があり、ストレージの使用量を減らしたいと思うかもしれません。列挙したオプションの中では、タグの削除が最も効果的なオプションです。ただし、タグの削除だけでは画像レイヤーは削除されず、基礎となる画像マニフェストがタグなしで残されるだけです。

より効果的に領域を解放するために、コンテナレジストリにはガベージコレクタがあり、参照されていないレイヤーと(オプションで)タグ付けされていないマニフェストを削除することができます。

ガベージコレクタを起動するには、gitlab-ctl が提供するregistry-garbage-collect コマンドを使用します。

caution
このコマンドは、ガベージコレクションの前にコンテナレジストリをシャットダウンし、ガベージコレクションが完了した後にのみ、再びコンテナレジストリを起動します。ダウンタイムを避けたい場合は、コンテナレジストリを手動で[読み取り専用gitlab-ctlモードに設定[し、gitlab-ctlgitlab-ctlを[バイパスするgitlab-ctlことができます。

ガベージコレクションの実行に必要な時間は、コンテナレジストリのデータサイズに比例します。

前提条件:

  • LinuxパッケージまたはGitLab Helmチャートを使ってGitLabをインストールしている必要があります。

コンテンツアドレス対応レイヤーを理解する

次の例では、まず画像を作成します:

# This builds a image with content of sha256:111111
docker build -t my.registry.com/my.group/my.project:latest .
docker push my.registry.com/my.group/my.project:latest

ここで、:latest を新しいバージョンで上書きします:

# This builds a image with content of sha256:222222
docker build -t my.registry.com/my.group/my.project:latest .
docker push my.registry.com/my.group/my.project:latest

現在、:latest タグはsha256:222222 のマニフェストを指しています。レジストリのアーキテクチャにより、このデータはmy.registry.com/my.group/my.project@sha256:111111 イメージを取り込む際にもアクセス可能ですが、:latest タグから直接アクセスすることはできません。

参照されないレイヤーの削除

イメージレイヤーはコンテナレジストリストレージの大部分を占めます。イメージマニフェストがレイヤーを参照していない場合、レイヤーは参照されていないと見なされます。参照されていないレイヤーはコンテナレジストリのガベージコレクタのデフォルトターゲットです。

設定ファイルのデフォルトの場所を変更していない場合は、実行してください:

sudo gitlab-ctl registry-garbage-collect

コンテナレジストリの場所を変更した場合config.yml

sudo gitlab-ctl registry-garbage-collect /path/to/config.yml

また、タグ付けされていないマニフェストと参照されていないレイヤーをすべて削除して、追加のスペースを回復することもできます。

タグなしマニフェストおよび参照なしレイヤーの削除

デフォルトでは、コンテナレジストリのガベージコレクタはタグ付けされていないイメージを無視します。ユーザーはタグ付けされていないイメージをダイジェストでプルし続けることができます。ユーザーは将来的にイメージを再タグ付けし、GitLab UIとAPIで再び見えるようにすることもできます。

タグ付けされていない画像や、その画像から参照されているレイヤーを気にしないのであれば、それらをすべて削除することができます。registry-garbage-collect コマンドで-m フラグを使います:

sudo gitlab-ctl registry-garbage-collect -m

タグなし画像の削除に不安がある場合は、レジストリデータをバックアップしてから行ってください。

ダウンタイムなしでガベージコレクションを実行

コンテナレジストリをオンラインに保ちながらガベージコレクションを実行するには、レジストリを読み取り専用モードにして、組み込みのgitlab-ctl registry-garbage-collect コマンドをバイパスします。

コンテナレジストリを読み取り専用モードにしている間は、イメージをプルすることはできますが、プッシュすることはできません。コンテナレジストリは、ガベージコレクションの全期間、読み取り専用モードのままでなければなりません。

デフォルトでは、レジストリの保存パスは /var/opt/gitlab/gitlab-rails/shared/registry です。

読み取り専用モードを有効にするには

  1. /etc/gitlab/gitlab.rb で、読み取り専用モードを指定します:

      registry['storage'] = {
        'filesystem' => {
          'rootdirectory' => "<your_registry_storage_path>"
        },
        'maintenance' => {
          'readonly' => {
            'enabled' => true
          }
        }
      }
    
  2. GitLab を保存して再設定します:

    sudo gitlab-ctl reconfigure
    

    このコマンドはコンテナレジストリを読み込み専用モードにします。

  3. 次に、ガベージコレクトコマンドのいずれかを起動します:

    # Remove unreferenced layers
    sudo /opt/gitlab/embedded/bin/registry garbage-collect /var/opt/gitlab/registry/config.yml
       
    # Remove untagged manifests and unreferenced layers
    sudo /opt/gitlab/embedded/bin/registry garbage-collect -m /var/opt/gitlab/registry/config.yml
    

    このコマンドはガベージコレクションを開始します。完了するまでの時間は、レジストリデータサイズに比例します。

  4. 完了したら、/etc/gitlab/gitlab.rb 、読み書きモードに戻してください:

     registry['storage'] = {
       'filesystem' => {
         'rootdirectory' => "<your_registry_storage_path>"
       },
       'maintenance' => {
         'readonly' => {
           'enabled' => false
         }
       }
     }
    
  5. GitLab を保存して再設定します:

    sudo gitlab-ctl reconfigure
    

スケジュールによるガベージコレクションの実行

レジストリのガベージコレクションは、レジストリが使用されていない週に定期的に実行するのが理想的です。最も簡単な方法は、週に一度定期的に実行する新しいcrontabジョブを追加することです。

/etc/cron.d/registry-garbage-collect にファイルを作成します:

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Run every Sunday at 04:05am
5 4 * * 0  root gitlab-ctl registry-garbage-collect

タグ付けされていないマニフェストと参照されていないレイヤーを削除するために、-m フラグを追加するとよいでしょう。

ガベージコレクションの停止

ガベージコレクションの停止が予想される場合は、ガベージコレクションをダウンタイムなしで実行する で説明したように、手動でガベージコレクションを実行する必要があります。ガベージコレクションを停止するには、Control+Cを押します。

そうでなければ、中断するとgitlab-ctl レジストリサービスがダウンしたままになる可能性が gitlab-ctlあります。この場合、gitlab-ctl システム上でガベージコレクションプロセスそのものを見つけ、 gitlab-ctlコマンドによってレジストリサービスを再び立ち上げられるようにするgitlab-ctl 必要が gitlab-ctlあります。

また、プロセスのマーク段階では、進行状況や結果を保存する方法はありません。blobが削除され始めると、永続的な処理が行われます。

GitLab とレジストリが別々のノードで実行されるように設定します(Linux パッケージのインストール)。

デフォルトでは、パッケージは両方のサービスが同じノード上で動作していることを前提としています。GitLabとレジストリを別々のノードで動作させるには、レジストリとGitLabで別々の設定が必要です。

レジストリの設定

GitLabとは別にレジストリを実行するために、/etc/gitlab/gitlab.rb で設定するオプションを以下に示します:

  • registry['registry_http_addr']デフォルトはプログラムで設定します。ウェブサーバ(またはLB)から到達可能である必要があります。
  • registry['token_realm']デフォルトはプログラムで設定します。認証に使うエンドポイントを指定します。通常は GitLab URL です。このエンドポイントはユーザーによって到達可能である必要があります。
  • registry['http_secret']ランダム文字列。状態を署名するためのランダムなデータで、改ざんを防ぐためにクライアントに保存されます。
  • registry['internal_key']デフォルトは自動生成。GitLabがトークンに署名するために使用するキーの内容。キーはレジストリサーバで作成されますが、そこでは使用されません。
  • gitlab_rails['registry_key_path']デフォルトはプログラムによって設定されます。これはinternal_key の内容がディスクに書き込まれるパスです。
  • registry['internal_certificate']デフォルトは自動的に生成されます。GitLabがトークンに署名するために使用する証明書の内容。
  • registry['rootcertbundle']デフォルトはプログラムによって設定されます。証明書へのパス。internal_certificate の内容がディスクに書き込まれるパスです。
  • registry['health_storagedriver_enabled']デフォルトはプログラムで設定します。構成されたストレージドライバのヘルスチェックを有効にするかどうかを設定します。
  • gitlab_rails['registry_issuer']デフォルト値。この設定はレジストリとGitLabで同じにする必要があります。

GitLab の設定

GitLabをレジストリから切り離して実行するために、/etc/gitlab/gitlab.rb で設定するオプションを以下に示します:

  • gitlab_rails['registry_enabled']trueに設定する必要があります。 この設定は、レジストリ API リクエストを許可するように GitLab に合図を送ります。
  • gitlab_rails['registry_api_url']デフォルトはプログラムで設定します。これは内部で使用されるレジストリURLで、ユーザーが操作する必要はありません。registry['registry_http_addr'] with scheme.
  • gitlab_rails['registry_host']例えば、registry.gitlab.example。スキームなしのレジストリエンドポイントで、エンドユーザーに表示されるアドレスです。
  • gitlab_rails['registry_port'].エンドユーザーに表示されるレジストリエンドポイントポート。
  • gitlab_rails['registry_issuer'] はレジストリ設定の発行者と一致しなければなりません。
  • gitlab_rails['registry_key_path']レ ジ ス ト リ 側で証明書に一致す る キーへのパス。
  • gitlab_rails['internal_key']GitLab がトークンの署名に使用するキーの内容。

GitLabコンテナレジストリのアーキテクチャ

GitLabレジストリはユーザーが自分のDockerイメージを保存するために使うものです。そのため、レジストリはクライアントフェイシング、つまりウェブサーバ(またはロードバランサ、略してLB)上に直接公開されます。

GitLab Registry diagram

上の図で説明した流れです:

  1. ユーザーがクライアント上でdocker login registry.gitlab.example を実行します。これはポート443でウェブサーバー(またはLB)に到達します。
  2. Webサーバは、レジストリバックエンドプールに接続します(デフォルトでは、ポート5000を使用)。ユーザーが有効なトークンを提供していないため、レジストリは 401 HTTP コードとトークンを取得するための URL (token_realm from Registry configuration) を返します。これは GitLab API を指しています。
  3. DockerクライアントはGitLab APIに接続し、トークンを取得します。
  4. APIはトークンをレジストリキーで署名し、Dockerクライアントに渡します。
  5. DockerクライアントはAPIから受け取ったトークンで再度ログインします。これでDockerイメージをプッシュしたりプルしたりできるようになります。

参考https://docs.docker.com/registry/spec/auth/token/

GitLabとレジストリ間の通信

レジストリには内部でユーザーを認証する方法がないので、GitLabに認証情報の検証を依存しています。レジストリとGitLabの接続はTLSで暗号化されています。鍵は GitLab がトークンに署名するために使い、証明書はレジストリがその署名を検証するために使います。デフォルトでは、すべてのインストールに対して自己署名証明書キーペアが生成されます。これは必要に応じて上書きすることができます。

GitLabはレジストリ秘密鍵を使ってレジストリとやり取りします。レジストリへのリクエストが発信されると、新しい短命(10分)の名前空間限定トークンが生成され、秘密鍵で署名されます。レジストリは、その署名が設定に指定されたレジストリ証明書と一致することを確認し、オペレーションを許可します。GitLabのバックグラウンドジョブ処理(Sidekiqを通して)もレジストリとやり取りします。これらのジョブはレジストリに直接話しかけて画像の削除を処理します。

サードパーティのレジストリからのマイグレーション

GitLabでの外部コンテナレジストリの使用はGitLab 15.8で非推奨となり、GitLab 16.0でサポート終了となりました。詳細は非推奨のお知らせをご覧ください。

GitLab 16.0ではインテグレーションは無効にはなっていませんが、デバッグやイシュー修正のサポートは提供されなくなりました。さらに、インテグレーションはもはや開発されておらず、新機能も強化されていません。サードパーティのレジストリ機能は、新しいGitLabコンテナレジストリバージョンがセルフマネージドで利用可能になった後、完全に削除されるかもしれません(エピック5521を参照)。GitLab Container Registryのみがサポートされる予定です。

このセクションでは、サードパーティレジストリから GitLab Container Registry にマイグレーションする管理者のためのガイダンスを示します。使用しているサードパーティのコンテナレジストリがここに記載されていない場合は、フィードバックイシューに使用例を記載してください。

以下で提供するすべての手順について、まずはテスト環境で試してみてください。本番環境で再現する前に、すべてが期待通りに動作することを確認してください。

Dockerディストリビューション・レジストリ

Docker Distribution RegistryはCNCFに寄贈され、現在はDistribution Registryとして知られています。このレジストリはGitLab Container Registryがベースにしているオープンソースの実装です。GitLabコンテナレジストリは、サポートされているすべてのストレージバックエンドを含め、ディストリビューションレジストリによって提供される基本的な機能と互換性があります。GitLab Container Registryにマイグレーションするには、このページの指示に従って、ディストリビューションレジストリと同じストレージバックエンドを使用することができます。GitLab Container Registryはディストリビューションレジストリと同じ設定を受け入れる必要があります。

トラブルシューティング

以下のセクションに入る前に、基本的なトラブルシューティングについて説明します:

  1. DockerクライアントとGitLabサーバーのシステムクロックが(NTPなどで)同期されていることを確認してください。

  2. S3-backedレジストリを使用している場合は、IAM権限とS3認証情報(リージョンを含む)が正しいか再確認してください。詳細については、サンプルのIAMポリシーを参照してください。

  3. レジストリのログ (/var/log/gitlab/registry/current など) と GitLab のプロダクションログ (/var/log/gitlab/gitlab-rails/production.log など) にエラーがないか確認しましょう。そこに手がかりがあるかもしれません。

コンテナレジストリでの自己署名証明書の使用

コンテナレジストリで自己署名証明書を使用している場合、CIジョブ中に以下のようなイシューが発生する可能性があります:

Error response from daemon: Get registry.example.com/v1/users/: x509: certificate signed by unknown authority

コマンドを実行するDockerデーモンは、認識されたCAによって署名された証明書を期待します。

GitLabはコンテナレジストリで自己署名証明書を使うことをサポートしていませんが、Dockerデーモンに自己署名証明書を信頼するように指示し、Dockerデーモンをマウントし、GitLab Runnerのconfig.toml ファイルにprivileged = falseprivileged = true の設定はDockerデーモンよりも優先されます:

  [runners.docker]
    image = "ruby:2.6"
    privileged = false
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]

これに関する追加情報:イシュー18239

Docker ログインに失敗しました:信頼できないキーで署名されたトークン

レジストリが GitLabの認証に依存している場合 レジストリが有効なログイン試行の認証に失敗すると、次のようなエラーメッセージが表示されます:

# docker login gitlab.company.com:4567
Username: user
Password:
Error response from daemon: login attempt to https://gitlab.company.com:4567/v2/ failed with status: 401 Unauthorized

さらに具体的には、/var/log/gitlab/registry/current のログファイルにこのようなメッセージが表示されます:

level=info msg="token signed by untrusted key with ID: "TOKE:NL6Q:7PW6:EXAM:PLET:OKEN:BG27:RCIB:D2S3:EXAM:PLET:OKEN""
level=warning msg="error authorizing context: invalid token" go.version=go1.12.7 http.request.host="gitlab.company.com:4567" http.request.id=74613829-2655-4f96-8991-1c9fe33869b8 http.request.method=GET http.request.remoteaddr=10.72.11.20 http.request.uri="/v2/" http.request.useragent="docker/19.03.2 go/go1.12.8 git-commit/6a30dfc kernel/3.10.0-693.2.2.el7.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.2 \(linux\))"

GitLabはレジストリの認証トークンを暗号化するために、証明書キーペアの両側の内容を使用しています。このメッセージは、これらの内容が一致していないことを意味します。

どのファイルが使用されているか確認してください:

  • grep -A6 'auth:' /var/opt/gitlab/registry/config.yml

     ## Container Registry Certificate
        auth:
          token:
            realm: https://gitlab.my.net/jwt/auth
            service: container_registry
            issuer: omnibus-gitlab-issuer
       -->  rootcertbundle: /var/opt/gitlab/registry/gitlab-registry.crt
            autoredirect: false
    
  • grep -A9 'Container Registry' /var/opt/gitlab/gitlab-rails/etc/gitlab.yml

     ## Container Registry Key
        registry:
          enabled: true
          host: gitlab.company.com
          port: 4567
          api_url: http://127.0.0.1:5000 # internal address to the registry, is used by GitLab to directly communicate with API
          path: /var/opt/gitlab/gitlab-rails/shared/registry
     -->  key: /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key
          issuer: omnibus-gitlab-issuer
          notification_secret:
    

これらのopenssl コマンドの出力は一致するはずで、証明鍵と鍵のペアが一致していることを証明します:

/opt/gitlab/embedded/bin/openssl x509 -noout -modulus -in /var/opt/gitlab/registry/gitlab-registry.crt | /opt/gitlab/embedded/bin/openssl sha256
/opt/gitlab/embedded/bin/openssl rsa -noout -modulus -in /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key | /opt/gitlab/embedded/bin/openssl sha256

証明書の2つの断片が一致しない場合は、ファイルを削除し、gitlab-ctl reconfigure を実行してペアを再生成します。ペアは、/etc/gitlab/gitlab-secrets.json に既存の値がある場合は、それを使用して再作成されます。新しいペアを生成するには、gitlab-ctl reconfigureを実行する前に、/etc/gitlab/gitlab-secrets.jsonregistry セクションを削除します。

自動生成された自己署名ペアを独自の証明書で上書きし、その内容が一致していることを確認した場合は、/etc/gitlab/gitlab-secrets.json の「レジストリ」セクションを削除して、gitlab-ctl reconfigure を実行できます。

AWS S3 で大きなイメージをプッシュすると GitLab レジストリのエラーが発生します。

GitLab レジストリで AWS S3 を使用している場合、大きなイメージをプッシュするとエラーが発生することがあります。レジストリのログで以下のエラーを確認してください:

level=error msg="response completed with error" err.code=unknown err.detail="unexpected EOF" err.message="unknown error"

このエラーを解決するには、レジストリ設定でchunksize を指定してください。25000000 (25 MB) と50000000 (50 MB) の間の値から始めてください。

Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb を編集します:

    registry['storage'] = {
      's3' => {
        'accesskey' => 'AKIAKIAKI',
        'secretkey' => 'secret123',
        'bucket'    => 'gitlab-registry-bucket-AKIAKIAKI',
        'chunksize' => 25000000
      }
    }
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)
  1. config/gitlab.yml を編集します:

    storage:
      s3:
        accesskey: 'AKIAKIAKI'
        secretkey: 'secret123'
        bucket: 'gitlab-registry-bucket-AKIAKIAKI'
        chunksize: 25000000
    
  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。

古いDockerクライアントのサポート

GitLabに同梱されているDockerコンテナレジストリは、デフォルトでschema1マニフェストを無効にします。古い Docker クライアント(1.9 以前)を使用している場合、イメージのプッシュでエラーが発生する可能性があります。詳しくはイシュー4145をご覧ください。

後方互換性のための設定オプションを追加することができます。

Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb を編集します:

    registry['compatibility_schema1_enabled'] = true
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)
  1. レジストリをデプロイしたときに作成した YAML 設定ファイルを編集します。次のスニペットを追加します:

    compatibility:
        schema1:
            enabled: true
    
  2. 変更を反映させるためにレジストリを再起動します。

Docker接続エラー

Docker接続エラーは、グループ名、プロジェクト名、ブランチ名のいずれかに特殊文字が含まれている場合に発生する可能性があります。特殊文字には以下のようなものがあります:

  • 先頭のアンダースコア
  • 末尾ハイフン/ダッシュ
  • ダブルハイフン/ダッシュ

これを回避するには、グループパスを変更したりプロジェクトパスを変更したりブランチ名を変更したりします。もうひとつの方法は、インスタンスレベルでこれを防ぐプッシュルールを作成することです。

画像のプッシュエラー

画像をプッシュしようとするとエラーや「リトライ」ループが発生するが、docker login は正常に動作する場合、NGINXによってレジストリに転送されるヘッダに問題がある可能性があります。推奨されるNGINXのデフォルト設定ではこの問題が解決されるはずですが、SSLがサードパーティのリバースプロキシにオフロードされているカスタム設定では発生する可能性があります。

この問題はDockerプロジェクトのイシューで議論されており、簡単な解決策はレジストリで相対URLを有効にすることです。

Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb を編集します:

    registry['env'] = {
      "REGISTRY_HTTP_RELATIVEURLS" => true
    }
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。

Self-compiled (source)
  1. レジストリをデプロイしたときに作成した YAML 設定ファイルを編集します。次のスニペットを追加します:

    http:
        relativeurls: true
    
  2. ファイルを保存してGitLab を再起動すると、変更が有効になります。

レジストリデバッグサーバーを有効にします。

コンテナレジストリデバッグサーバーを使用して、問題を診断できます。デバッグエンドポイントは、メトリクスと健全性を監視し、プロファイリングを実行できます。

caution
デバッグ・エンドポイントから機密情報を利用できる場合があります。本番環境では、デバッグ・エンドポイントへのアクセスをロックする必要があります。

オプションのデバッグサーバーは、gitlab.rb 設定でレジストリデバッグアドレスを設定することで有効にできます。

registry['debug_addr'] = "localhost:5001"

設定を追加した後、変更を適用するためにGitLabを再設定してください。

curl を使ってデバッグサーバーにデバッグ出力を要求します:

curl "localhost:5001/debug/health"
curl "localhost:5001/debug/vars"

古いスキーマv1 Dockerイメージへのアクセス

schema V1イメージマニフェストを含む、DockerレジストリAPI V1のサポートが終了しました:

GitLabコンテナレジストリからv1イメージをプッシュまたはプルすることができなくなりました。

GitLab 13.9へのアップグレードに先立ち、GitLab Container Registryにv1イメージをアップグレード(Dockerが推奨する手順)しなかった場合、これらのイメージにはアクセスできなくなります。これらのイメージをプルしようとすると、このエラーが表示されます:

  • Error response from daemon: manifest invalid: Schema 1 manifest not supported

セルフマネージド GitLab インスタンスでは、GitLab コンテナレジストリをv3.0.0-gitlab よりも低いバージョンに一時的にダウングレードすることで、これらのイメージへのアクセスを取り戻すことができます。これらのイメージへのアクセスを取り戻すには、以下の手順に従ってください:

  1. コンテナレジストリをv2.13.1-gitlab にダウングレードします。
  2. v1イメージをアップグレードします。
  3. コンテナレジストリのダウングレードを元に戻します。

イメージのアップグレード処理中に、レジストリを読み取り専用モードにする必要はありません。v3.0.0-gitlab 以降に導入された新機能に依存していないことを確認してください。こ の よ う な機能は、 ア ッ プグ レー ド 処理中は利用で き ません。詳しくはレジストリの変更履歴をご覧ください。

以下の項では、各インストール方法の詳細について説明します。

Helm chart (Kubernetes)

Helmチャートのインストールの場合:

  1. image.tag の設定パラメータをv2.13.1-gitlab で上書きしてください。
  2. 再起動します。
  3. イメージのアップグレード)の手順を実行します。
  4. image.tag パラメータを以前の値に戻します。

その他のレジストリ設定の変更は必要ありません。

Linux package (Omnibus)

Linuxパッケージ・インストールの場合:

  1. GitLab 13.9+に同梱されているレジストリ・バイナリをv3.0.0-gitlab より前のものに一時的に置き換えてください。そのためには、v2.13.1-gitlabのような、GitLabコンテナ・レジストリ用のDockerイメージの前のバージョンを引っ張ってきてください。そして、このイメージの内部から/bin/registry にあるregistry バイナリを取得します:

    id=$(docker create registry.gitlab.com/gitlab-org/build/cng/gitlab-container-registry:v2.13.1-gitlab)
    docker cp $id:/bin/registry registry-2.13.1-gitlab
    docker rm $id
    
  2. /opt/gitlab/embedded/bin/registry にある Linux パッケージのインストールに組み込まれているバイナリをregistry-2.13.1-gitlabに置き換えてください。Linux パッケージに埋め込まれている元のバイナリをバックアップしておき、イメージのアップグレード手順を実行した後に復元してください。バイナリを置き換える前にレジストリサービスを停止し、置き換えた直後にレジストリサービスを開始する必要があります。レジストリ設定の変更は必要ありません。

Self-compiled (source)

registry のバイナリを探し、Linux パッケージのインストールで説明したように、v3.0.0-gitlabから取得したバイナリに一時的に置き換えてください。必ず元のレジストリバイナリをバックアップしておき、イメージのアップグレード手順を実行した後で復元してください。

イメージのアップグレード

v1イメージをアップグレードするには、Dockerが推奨する手順に従ってください。最も簡単な方法は、v1.12以上のDockerクライアントを使用して、イメージをプルしてレジストリに再度プッシュすることです。Dockerはイメージをレジストリにプッシュする前に自動的に変換します。これでv1イメージがv2イメージとして利用できるようになります。

名前が空のタグ

AWS DataSyncを使用してレジストリデータを S3 バケットへ、または S3 バケット間でコピーする場合、宛先バケット内の各コンテナリポジトリのルートパスに空のメタデータオブジェクトが作成されます。これにより、レジストリはそのようなファイルを GitLab UI や API に名前のないタグとして表示されると解釈します。詳細については、このイシューを参照してください。

この問題を解決するには、2つのうちの1つを行います:

  • AWS CLIrm コマンドを使用して、影響を受ける各リポジトリのルートから空のオブジェクトを削除します。末尾の/ に特に注意し、--recursive オプションを使用しないようにしてください:

     aws s3 rm s3://<bucket>/docker/registry/v2/repositories/<path to repository>/
    
  • AWS CLIsync コマンドを使用して、レジストリデータを新しいバケットにコピーし、それを使用するようにレジストリを設定します。これにより、空のオブジェクトが残ります。

高度なトラブルシューティング

具体的な例を使って、S3のセットアップに関する問題を診断する方法を説明します。

クリーンアップポリシーの調査

クリーンアップポリシーでタグが削除されたり削除されなかったりした理由がわからない場合は、Railsコンソールから以下のスクリプトを実行してポリシーを一行ずつ実行してください。これはポリシーの問題を診断するのに役立ちます。

repo = ContainerRepository.find(<project_id>)
policy = repo.project.container_expiration_policy

tags = repo.tags
tags.map(&:name)

tags.reject!(&:latest?)
tags.map(&:name)

regex_delete = ::Gitlab::UntrustedRegexp.new("\\A#{policy.name_regex}\\z")
regex_retain = ::Gitlab::UntrustedRegexp.new("\\A#{policy.name_regex_keep}\\z")

tags.select! { |tag| regex_delete.match?(tag.name) && !regex_retain.match?(tag.name) }

tags.map(&:name)

now = DateTime.current
tags.sort_by! { |tag| tag.created_at || now }.reverse! # Lengthy operation

tags = tags.drop(policy.keep_n)
tags.map(&:name)

older_than_timestamp = ChronicDuration.parse(policy.older_than).seconds.ago

tags.select! { |tag| tag.created_at && tag.created_at < older_than_timestamp }

tags.map(&:name)
  • スクリプトは削除するタグのリストを作成します (tags)。
  • tags.map(&:name) は削除するタグのリストを表示します。これは長いオペレーションになるかもしれません。
  • 各フィルターの後、tags のリストをチェックし、破棄するタグが含まれているかどうかを確認します。

プッシュ中の予期しない403エラー

ユーザーが S3-backed レジストリを有効にしようとしました。docker login 。しかし、画像をプッシュすると、出力が表示されました:

The push refers to a repository [s3-testing.myregistry.com:5050/root/docker-test/docker-image]
dc5e59c14160: Pushing [==================================================>] 14.85 kB
03c20c1a019a: Pushing [==================================================>] 2.048 kB
a08f14ef632e: Pushing [==================================================>] 2.048 kB
228950524c88: Pushing 2.048 kB
6a8ecde4cc03: Pushing [==>                                                ] 9.901 MB/205.7 MB
5f70bf18a086: Pushing 1.024 kB
737f40e80b7f: Waiting
82b57dbc5385: Waiting
19429b698a22: Waiting
9436069b92a3: Waiting
error parsing HTTP 403 response body: unexpected end of JSON input: ""

このエラーは曖昧で、403がGitLab Railsアプリケーションから来ているのか、Dockerレジストリから来ているのか、それとも他の何かから来ているのかがはっきりしません。この場合、ログインが成功したことはわかっているので、おそらくクライアントとレジストリ間の通信を調べる必要があるでしょう。

Dockerクライアントとレジストリ間のREST APIはDockerドキュメントに記載されています。通常、Wiresharkやtcpdumpを使ってトラフィックをキャプチャし、どこで問題が発生したかを確認します。しかし、Dockerクライアントとサーバ間の通信はすべてHTTPSで行われるため、秘密鍵がわかっていてもトラフィックを素早く復号化するのは少々困難です。代わりに何ができるでしょうか?

1つの方法は、安全でないレジストリを設定することでHTTPSを無効にすることです。これはセキュリティホールを引き起こす可能性があり、ローカルでのテストにのみ推奨されます。本番システムでこのようなことができない、あるいはしたくない場合は、Man-in-the-Middle Proxyの略であるmitmproxyを使うという方法もあります。

mitmproxy

mitmproxyを使うと、クライアントとサーバーの間にプロキシを置き、 すべてのトラフィックを検査することができます。この機能を使うには、システムが mitmproxy SSL 証明書を信頼する必要があります。

以下のインストール手順は、Ubuntu を実行していることを前提としています:

  1. mitmproxy をインストールします。
  2. mitmproxy --port 9000 を実行して証明書を生成します。CTRL-C を入力して終了します。
  3. ~/.mitmproxy から証明書をシステムにインストールします:

    sudo cp ~/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy-ca-cert.crt
    sudo update-ca-certificates
    

成功すると、証明書が追加されたことが出力されます:

Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.

証明書が正しくインストールされていることを確認するには、以下を実行します:

mitmproxy --port 9000

このコマンドは、ポート9000 で mitmproxy を実行します。別のウィンドウで次のコマンドを実行します:

curl --proxy "http://localhost:9000" "https://httpbin.org/status/200"

すべてが正しく設定されていれば、mitmproxy ウィンドウに情報が表示され、curl コマンドによるエラーは発生しません。

プロキシを使用した Docker デーモンの実行

Dockerがプロキシ経由で接続するには、適切な環境変数でDockerデーモンを起動する必要があります。最も簡単な方法は、Dockerをシャットダウンしてから(例えばsudo initctl stop docker )、Dockerを手動で実行することです。rootで実行します:

export HTTP_PROXY="http://localhost:9000"
export HTTPS_PROXY="https://localhost:9000"
docker daemon --debug

このコマンドはDockerデーモンを起動し、すべての接続をmitmproxy経由でプロキシします。

Docker クライアントの実行

mitmproxyとDockerが起動したので、サインインしてコンテナイメージをプッシュしてみましょう。これを行うには root として実行する必要があるかもしれません。例えば

docker login s3-testing.myregistry.com:5050
docker push s3-testing.myregistry.com:5050/root/docker-test/docker-image

上の例では、mitmproxy ウィンドウに次のようなトレースが表示されます:

mitmproxy output from Docker

上の画像は

  • 最初のPUTリクエストは201ステータスコードで問題なく通過しました。
  • 201はクライアントをS3バケットにリダイレクトしました。
  • AWSバケットへのHEADリクエストは403 Unauthorizedをレポーターしました。

これは何を意味するのでしょうか?これは、S3ユーザーがHEADリクエストを実行するための正しい権限を持っていないことを強く示唆しています。解決策:IAM権限をもう一度確認してください。正しい権限が設定されると、エラーは消えます。

gitlab-registry.key が見つからないため、コンテナリポジトリの削除ができません。

GitLab インスタンスのコンテナレジストリを無効にして、コンテナリポジトリを持つプロジェクトを削除しようとすると、以下のエラーが発生します:

Errno::ENOENT: No such file or directory @ rb_sysopen - /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key

この場合は、以下の手順に従ってください:

  1. gitlab.rb のコンテナレジストリのインスタンスワイド設定を一時的に有効にします:

    gitlab_rails['registry_enabled'] = true
    
  2. ファイルを保存し、変更を有効にするためにGitLab を再設定してください。
  3. もう一度削除を試してください。

それでも一般的な方法でリポジトリを削除できない場合は、GitLab Rails コンソールを使ってプロジェクトを強制的に削除することができます:

# Path to the project you'd like to remove
prj = Project.find_by_full_path(<project_path>)

# The following will delete the project's container registry, so be sure to double-check the path beforehand!
if prj.has_container_registry_tags?
  prj.container_repositories.each { |p| p.destroy }
end