株式会社ネットワールドのエンジニアがお届けする技術情報ブログです。
各製品のエキスパートたちが旬なトピックをご紹介します。

GitとCI/CDに関する知識ゼロのSEが、GitLabでCI/CDパイプラインを使ってコンテナレジストリにイメージを登録する話

皆様こんにちは。SEの小池と申します。

GitLabのCI/CDパイプラインでは本当にいろいろなことができます。
その中でも主要なステージとしてビルドが挙げられるかと存じます。
今回はそのビルドに関連して、GitLabのコンテナレジストリ機能の有効化手順と、CI/CDパイプラインで任意のイメージをコンテナレジストリに登録する方法をご紹介いたします。

本記事の対象の方

  • GitLab オンプレミス版 (Self-Managed) でコンテナレジストリを有効にしたい方。
  • 手動でGitLabにコンテナイメージを登録してみたい方。
  • CI/CDパイプラインを使ってコンテナイメージを登録してみたい方。

今回のブログのゴール

このブログのゴールはこちらです。

今回のゴール
  • GitLabのコンテナレジストリにコンテナイメージを登録する

このブログをお読みいただくにあたっての事前ご連絡事項

  • 本記事はオンプレミス版 (Self-Managed) のGitLab Enterprise Edition 14.10.4-ee (Ultimate) における仕様をベースに記載しております。それ以外のエディションやバージョンではこの記事に記載の通りではない可能性がございます。
  • 本記事で紹介しているコンテナレジストリの有効化の手順は、OmnibusのGitLabを利用時の手順となります。ソースからインストールしたGitLabでコンテナレジストリを有効化する手順はGitLab Docs (こちら) をご参照ください。
  • 本記事では既存のGitLabドメインでコンテナレジストリを構成します。別のドメインでコンテナレジストリを構成なさりたい場合はGitLab Docs (こちら) をご参照ください。
  • 本記事のGitLabのGUIは日本語にローカライズした状態で掲載しております。それ以外の言語をご利用の方は適宜読み替えてください。

GitLabのコンテナレジストリの概要

ご存じの通り、Dockerにはレジストリという機能が存在します。
GitLabはDockerのレジストリを統合しており、GitLabのコンテナレジストリ機能でこれを使用することができます。
GitLabはプロジェクト単位でDockerイメージを格納するための独自のスペースを持つことができます。
下図のように、特定のプロジェクトの独自スペースに登録することで、プロジェクトのGUIからも確認することができます。
参考 : GitLab Container Registry | GitLab

使い方は基本的にDockerのレジストリと同じです。
docker push コマンドで手動でイメージを登録することはもちろん、CI/CDパイプラインの中でビルドしたイメージを登録することも可能です。
ただ、プロジェクト独自のスペースにイメージを登録することを実現するためにイメージの命名規則が決められていますので、基本的にはこれを遵守する必要があります。
参考 : GitLab Container Registry | GitLab

登録したコンテナイメージは基本的にGitLabのサーバー上に保管されています。
したがって、GitLabサーバーにて docker images コマンドでレジストリを一覧表示すると、GitLabのコンテナレジストリで登録したイメージも表示されます。

使いやすい反面、あまりたくさんのイメージを登録するとGitLabサーバーのストレージをたくさん消費してしまうため、注意が必要です。
一応これを防止するためのクリーンアップポリシーを設定することも可能です。
参考 : Reduce Container Registry Storage | GitLab

GitLabのコンテナレジストリ機能は SaaS版 及び オンプレミス版 (Self-Managed) の両方で利用可能です。
また、全てのティアで利用可能なので、無償版をご利用中の方も是非お試しいただければと存じます。

Step1 : コンテナレジストリ機能の状態確認

SaaS版の GitLab.com では既にコンテナレジストリ機能は有効になっています。
オンプレミス版 (Self-Managed) 且つ OmnibusのGitLabをご利用中の場合、環境によってコンテナレジストリ機能は有効になっている場合と無効になっている場合があります。
GitLab Docsを参照する限り、以下を両方満たす場合は既にコンテナレジストリ機能は有効になっているようです。

  • 組み込みの Let'sEncrypt 統合を使用している。
  • GitLab 12.5 以降を使用している。

参考 : GitLab Container Registry administration | GitLab

上記の条件でも判断可能ですが、ご利用中の環境でコンテナレジストリが有効か無効かを確認するもっとも簡単な方法としては、GUIから対象のプロジェクトのページの [パッケージとレジストリ]>[コンテナレジストリ] メニューが有るか無いかを確認します。
有ればコンテナレジストリ機能は有効になっていて、無ければコンテナレジストリ機能は無効になっています。

Step2 : コンテナレジストリの有効化 (オンプレミス版 且つ Omnibus Installの場合)

オンプレミス版 (Self-Managed) では、OmnibusのGitLabをご利用中の場合と、ソースからインストールしたGitLabをご利用中の場合で有効化の手順が異なります。
本章では、オンプレミス版 (Self-Managed) 且つ OmnibusのGitLabをご利用中の場合における、コンテナレジストリの有効化手順をご紹介いたします。

ソースからインストールしたGitLabにおける手順について
ソースからインストールしたGitLabにてコンテナレジストリをご利用になりたい方は、誠に恐れ入りますがGitLab Docs (こちら) をご参照のください。

また、本章の手順は既存のGitLabのドメインでコンテナレジストリを構成します。
これによりポートでレジストリを公開することとなり、結果的に既存のTLS証明書を使いまわすことができます。

既存のGitLabドメインとは異なるドメインでコンテナレジストリを構成する場合
既存のGitLabドメインとは異なるドメインでコンテナレジストリを構成なさりたい場合はGitLab Docs (こちら) をご参照ください。

有効化の手順ではGitLabの構成ファイルであるgitlab.rbを編集します。
オンプレミス版 (Self-Managed) 且つ OmnibusのGitLab をDocker Composeなどで起動している場合は、docker-compose.ymlファイルや引数で設定することも可能です。
ご利用の環境に適していると思われる方法で実装なさってください。

まずGitLabをインストールしているOSにサインインし、既存の構成ファイル/etc/gitlab/gitlab.rbのバックアップを取得します。

次に、構成ファイル/etc/gitlab/gitlab.rbをエディタ等で開きます。 以下の行のコメントを外し、編集します。

registry_external_url '<任意のURL>:<レジストリを公開する任意ポート>'
今回のブログにおいては、URLはGitLabドメインと同じドメインを指定します。
例えば当方の検証環境の場合。
GitLabの公開URLであるexternal_urlhttps://gitlabblog.example.comです。
TLS証明書を使いまわしたいので、registry_external_urlexternal_urlとおなじ文字列を指定します。
ポートはひとまずGitLab Docsの例にある5050を設定するとした場合、以下の通りとなります。
registry_external_url 'https://gitlabblog.example.com:5050'

次に、もし/etc/gitlab/ssl/にGitLabのTLS証明書とキーが格納されていない場合は、上記に加え以下の行のコメントを外し、各ファイルへのパスを記載します。

registry_nginx['ssl_certificate'] = "<TLS証明書へのフルパス>"
registry_nginx['ssl_certificate_key'] = "<キーへのフルパス>"
参考 : GitLab Container Registry administration | GitLab

構成ファイルである/etc/gitlab/gitlab.rbを保存します。
続けて以下のコマンドでGitLabを再構成します。

sudo gitlab-ctl restart

GitLabの再構成が完了したら、GUIから対象のプロジェクトのページの [パッケージとレジストリ]>[コンテナレジストリ] メニューが有ることを確認します。

コンテナレジストリの有効化 (オンプレミス版 且つ Omnibus Installの場合) は以上となります。

Step3 : コンテナレジストリにコンテナイメージを登録する

前の手順で有効にしたコンテナレジストリに、任意のコンテナイメージを登録してみましょう。

Case1 : 手動でイメージをプッシュする場合

手動でDockerコマンドを実行し、先ほど有効にしたコンテナレジストリに任意のコンテナイメージを登録します。

GitLabのGUIに任意ユーザーでサインインし、対象のプロジェクトの[パッケージとレジストリ]>[コンテナレジストリ]をクリックします。

画面に3つのコマンドが記載されています。
一番上のコマンドが、Dockerレジストリにサインインするためのコマンドです。
このコマンドをコピーします。

任意の端末で先ほどコピーしたコマンドを実行します。
するとログインユーザーを聞かれますので、GitLab側で使っているユーザーでログインします。
(コンテナレジストリにイメージをプッシュするには、対象のプロジェクトでDeveloperMaintainerOwnerのいずれかのロールを持つユーザーである必要があります。)
例えばGitLabにdev01というユーザーがいて、このユーザーでログインする場合は以下のようなコマンドの流れになります。

$ docker login gitlabblog.example.com:5050
Username: dev01
Password:

無事ログイン出来たら任意のディレクトリに移動して、今回お試しでコンテナレジストリに登録するコンテナイメージのためにDockerfileを作成します。
Dockerfikeの内容は任意で構いません。

ここまで出来たら先ほどのGitLabのGUI画面に戻ります。
2個目のコマンドはこのプロジェクトのコンテナレジストリに登録するために必要なタグをつけてビルドするためのコマンドです。
このコマンドをコピーします。

クライアント側に戻ります。
先ほどDockerfileを作成したディレクトリで、GitLabのGUIでコピーしたコマンドを実行します。
最終的にビルドとタグ付けが正常に完了したメッセージが出力されることを確認します。

再びGitLabのGUI画面に戻ります。
3つ目のコマンドはこのプロジェクトのコンテナレジストリに、今ビルドしたイメージをプッシュするためのコマンドです。
このコマンドをコピーします。

クライアント側に戻り、GitLabのGUIでコピーしたコマンドを実行します。
最終的に出力にエラーが無く、プッシュが完了したことを確認します。

プッシュコマンドが成功したらGitLabのGUIに戻り、F5キーをそっと押します。
正常にイメージを登録できている場合は、以下の通りコンテナレジストリ画面にエントリが表示されます。
ヤッタネ!!

以上が手動でイメージをプッシュする場合の手順でした。

Case2 : CI/CDパイプランでイメージをビルドしてプッシュする場合

GitLabのCI/CDパイプラインで任意のコンテナイメージをビルドし、それをコンテナレジストリに登録します。
この手順ではエクゼキューターがDockerのRunnerが必要になります。
エクゼキューターがDockerのRunnerが未登録の場合は、GitLab Docs (こちら) をご参照いただき、先に登録をお願い致します。

任意のユーザーでGitLabのGUIにサインインし、対象のプロジェクトに移動します。
まず、今回レジストリに登録するためのイメージをビルドするために、Dockerfileを作成します。
もし既に登録したいイメージをビルドするコードなどがそろっている方は、この手順を飛ばして.gitlab-.ci.ymlファイルの作成から実施してください。
プロジェクトのトップページでリポジトリ一覧の少し上にある [+] をクリックし、[新規ファイル] をクリックします。

画面上部、[main /] と表示されている横のテキストボックスにDockerfileと入力します。
Dockerfileの中身は任意に設定してください。
完了したらコミットメッセージなどを任意に設定し、[Commit changes] をクリックします。

前の手順でマージリクエストを作成するように設定した場合は、続けてマージリクエストの設定画面に遷移するので、任意の内容でマージリクエストを作成してください。

続けて、.gitlab-ci.ymlファイルを作成します。
既に.gitlab-ci.ymlファイルがある場合は、追記でも構いません。
プロジェクトのトップページに戻り、画面上部で先ほど作成したブランチ (前の手順でmainブランチに直接コミットした場合はmainブランチ) を選択し、[+] > [新規ファイル] をクリックします。

画面上部、[<Dockerfileをコミットしたブランチ名> /] と表示されている横のテキストボックスに.gitlab-ci.ymlと入力します。
.gitlab-ci.ymlファイルの中身の設定例は以下の通りです。
以下の例をそのまま利用していただいても構いませんし、アレンジしていただいて問題ありません。
ただしアレンジする場合、イメージの命名規則についてこちらのGitLab Docsをご参照ください。

stages:
  - build

SampleJob-Buld-And-Push:
  stage: build
  image: docker:20.10.17
  services:
  - docker:20.10.17-dind
  variables:
    # ビルドイメージの変数作成
    IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
  script:
  # 各種変数の値の出力 (目視確認用)
  - echo $CI_REGISTRY_IMAGE
  - echo $CI_COMMIT_REF_SLUG
  - echo $CI_COMMIT_SHA
  - echo $IMAGE
  - echo $CI_REGISTRY_USER
  - echo $CI_REGISTRY_PASSWORD
  - echo $CI_REGISTRY
  # ビルド
  - docker build --tag $IMAGE .
  # Dockerレジストリにログイン
  - docker login --username $CI_REGISTRY_USER --password $CI_REGISTRY_PASSWORD $CI_REGISTRY
  # ビルドしたイメージをプッシュ
  - docker push $IMAGE 
上の.gitlab-ci.ymlファイルで使用している変数については【余談】.gitlab-ci.ymlで使用した各種変数についてで概要を説明を致しますので、ここでの説明は割愛致します。
記載が完了したらコミットメッセージなどを任意に設定し、[Commit changes] をクリックします。

コミットするとCI/CDパイプラインが実行され始めるので、完了するまでお待ちください。
CI/CDパイプラインの状態は [CI/CD]>[パイプライン] で表示されるパイプライン一覧の一番上のステータスから確認できます。
[成功] と表示されていればOKです。

CI/CDパイプラインが成功していればイメージがコンテナレジストリに登録されているはず…です。
[パッケージとレジストリ]>[コンテナレジストリ]を開き、イメージが登録されていることを確認します。
あ、良かった。登録されてた!セーフ!!

以上がCI/CDパイプランでイメージをビルドしてプッシュする場合の手順でした。

【余談】.gitlab-ci.ymlで使用した各種変数について

今回のCI/CDパイプラインで使用した変数の概要を述べます。
概要欄に "定義済みの変数" と記載しているものについては、GitLabで事前に定義されている変数です。
なお、先述した.gitlab-ci.ymlファイルで echo コマンドでこれら変数の内容を出力しているので、CI/CDパイプラインのログから設定値を確認することができます。

変数名概要
$CI_REGISTRY_IMAGE定義済みの変数。
プロジェクトのコンテナレジストリのアドレス。プロジェクトでコンテナレジストリが有効になっている場合にのみ使用可。

例) <GitLabコンテナレジストリの公開URL>:<ポート番号>/<グループ名>/<プロジェクト名>
$CI_COMMIT_REF_SLUG定義済みの変数。
プロジェクトがビルドされるブランチまたはタグの名前を小文字にして63バイトに短縮し、0-9とa-z以外を-に置き換えたもの。先頭/末尾の-は不可。URL、ホスト名、ドメイン名で使用する。

例) 今回の場合だとDockerfile.gitlab-ci.ymlファイルをコミットしたブランチ名。
$CI_COMMIT_SHA定義済みの変数。
プロジェクトが構築されているコミットのリビジョン。
$CI_REGISTRY_USER定義済みの変数。
コンテナをプロジェクトのGitLabコンテナレジストリにプッシュするためのユーザー名。プロジェクトでコンテナレジストリが有効になっている場合にのみ使用可。

例) gitlab-ci-token
$CI_REGISTRY_PASSWORD定義済みの変数。
コンテナをプロジェクトのGitLabコンテナレジストリにプッシュするためのパスワード。プロジェクトでコンテナレジストリが有効になっている場合にのみ使用可。このパスワードは別の変数CI_JOB_TOKENと同じであり、ジョブが実行されている間のみ有効。なお、設定値はマスクされており、echoなどで直接出力することができない。
$CI_REGISTRY定義済みの変数。
GitLabのコンテナレジストリのアドレス。プロジェクトでコンテナレジストリが有効になっている場合にのみ使用可。:portでポート番号を指定してコンテナレジストリを構成している場合は、この変数にポート番号まで含まれる。

例) <GitLabコンテナレジストリの公開URL>:<ポート番号>
$IMAGE今回のCI/CDパイプラインでカスタムで作成した変数。
GitLab Docs (こちら) にある命名規則に則ったイメージ名を付与するために作成した変数。

参考 : Predefined variables reference | GitLab

【余談】筆者による苦悩のトライアンドエラー

この章では、本ブログを書くにあたり筆者が遭遇したエラーについて、回避方法をご紹介いたします。
もし同じエラーが出た際の参考になれば幸いです。

プライベートCAで発行した証明書が信用できないよエラー

手動でイメージ登録するためにログインコマンドをクライアント側で実行した際に出たエラーです。

$ docker login <registry_external_urlで指定したドメイン>:<registry_external_url で指定したポート>
Username: <GitLab側のユーザー名>
Password:
Error response from daemon: Get "https://<registry_external_urlで指定したドメイン>:<registry_external_url で指定したポート>/v2/": x509: certificate signed by unknown authority

GitLabではなくクライアント側のセキュリティ設定に起因して出たエラーです。
特に当方の検証環境はプライベートCAで発行した証明書を利用しているため、このエラーはほぼ確実に出ます。
今回のブログの場合はコンテナレジストリをGitLabと同じドメインで公開しているので、GitLabサーバーの証明書 もしくは CAのルート証明書をクライアントにインストールすることで回避できます。

GitLab側のホスト名解決できないよエラー

CI/CDパイプラインでイメージをビルドしようとしたときに出現したエラーです。

fatal: unable to access 'https://<GitLabの公開URL>/<グループのID>/<プロジェクトのID>.git/': Could not resolve host: <GitLabの公開URL>

このエラーはエクゼキューターがDockerのRunner特有のエラーで、ネットワークモードをhostにすることで回避できます。
Runnerの設定ファイルであるconfig.tomlファイルの [runners.docker] セクションに network_mode = "host" と追記します。

参考 : The Docker executor | GitLab

dockerコマンド実行すると接続が失敗するよエラー

CI/CDパイプラインでイメージをビルドしようとしたときに出現したエラーです。

error during connect: Post "http://docker:2375/v1.24/build?buildargs=<中略>": dial tcp: lookup docker: Try again

これについてはRunnerの設定ファイルであるconfig.tomlファイルの [volumes] セクションに "/var/run/docker.sock:/var/run/docker.sock" を追記することで回避できます。

最後に

この度はGitもCI/CDもよくわかっていないど素人SEによるGitLab検証ブログをお読みいただき、誠にありがとうございます。
このブログの目標は以下のとおりでしたが、皆さまはいかがでしたでしょうか。


今回のゴール
  • GitLabのコンテナレジストリにコンテナイメージを登録する

今回の記事、実はコンテナイメージのスキャンまで書く予定だったのですが、文字数が多くなりすぎるので断念致しました。すごく残念。
次回以降、コンテナイメージのスキャンについてもご紹介できればと存じます。
この記事がGitLabを触り始めた方の一助となれば幸いにございます。


GitLabに関するお問い合わせは、以下のフォームからお願い致します。
GitLab製品 お問い合わせ

今までのGitLabの検証ブログはこちらです。
GitLab カテゴリーの記事一覧 - ネットワールド らぼ

GitLab操作デモ動画 (基本編) を作ってみました。(音声の録音は自宅でiPhoneのボイスメモ使うという超低クオリティですが…。)
つたない内容ではありますが、ご興味がおありでしたら是非ご視聴いただければと存じます。

www.youtube.com