こんにちは。テクマトリックスの米田です。
DockerHubにはプライベートレジストリを構築するためのregistryイメージが登録されています。今回はこのregistryイメージを使ってプライベートレジストリを構築し、Jenkinsを活用してDockerfileからビルドしたDockerイメージをプライベートレジストリに格納する手法を試してみたので、本記事でその手法をまとめます。

レジストリとは

Dockerのレジストリ(Registry)は、Dockerイメージを保存・管理し、必要に応じて取得(pull)やアップロード(push)を行うための仕組みです。レジストリには、外部に公開されているパブリックレジストリと、外部に非公開のプライベートレジストリがあります。

・パブリックレジストリ
レジストリのうち、外部に公開されているものをパブリックレジストリといい、代表的なものとしてDocker Hubが挙げられます。Docker Hubには多くの公式なDockerイメージが格納されており非常に便利ですが、外部に公開されている分、自社内で作成したイメージを格納するにあたってはプライバシーやアクセス制御といったセキュリティに関する問題が発生します。

・プライベートレジストリ
外部に非公開で、社内や特定の環境でのみ利用可能な独自のレジストリをプライベートレジストリといいます。オンプレミス環境で外部ネットワークにアクセスできない場合や、企業のセキュリティポリシー上、外部のパブリックレジストリを利用できない場合に有効です。よく利用されるプライベートレジストリの例としてはAmazon ECRGoogle Artifact RegistryAzure Container Registryが挙げられます。

プライベートレジストリの構築

構築手順

今回のプライベートレジストリの構築には、DockerHubで公式に公開されているregistryイメージを使用します。registryイメージを用いたプライベートレジストリの構築は、Dockerが利用できさえすれば誰でも試すことができます。

まずはregistryイメージをプルします。

$ docker image pull registry:2.8.3
$ docker image ls

registryイメージの公式ページに記載のコマンドを基に、プルしたregistryイメージをビルドしてプライベートレジストリのDockerコンテナを起動します。

$ docker run -d -p 5000:5000 --restart always --name registry registry:2.8.3
$ docker container ls

動作確認

プライベートレジストリが正常に起動しているか確認します。以下のcurlコマンドを実行することでプライベートレジストリに格納されているイメージのリポジトリ名を確認することができます。初期状態では空です。

$ curl http://localhost:5000/v2/_catalog

起動したプライベートレジストリにイメージをプッシュしてみます。今回は公式のhello-worldイメージをプルして、それをプライベートレジストリにプッシュできるようイメージ名を変更し、プライベートレジストリにプッシュします。

$ docker pull hello-world
$ docker tag hello-world localhost:5000/my-hello-world:0.0.1
$ docker image push localhost:5000/my-hello-world:0.0.1
$ curl http://localhost:5000/v2/_catalog

以下のコマンドを実行することでリポジトリに格納されているイメージのタグ一覧を確認できます。

$ curl http://localhost:5000/v2/<リポジトリ名>/tags/list

イメージがプッシュされていることが確認出来たら、最後にイメージをプル出来るか確認します。
プライベートレジストリに格納したイメージをローカルから削除し、再度プライベートレジストリからイメージを取得します。

$ docker rmi localhost:5000/my-hello-world:0.0.1
$ docker pull localhost:5000/my-hello-world:0.0.1
$ docker image ls

CI環境の構築

前提

Windows 10 ProにVirtual Boxをインストールし、この仮想環境に構築したUbuntu 24.04で各ツールをインストールしました。今回インストールしたツールとバージョンは以下の通りです。

Jenkins2.492.1
GitLab17.9.1
Docker28.0.1

JenkinsとGitLabのインストール方法はそれぞれ以下の公式ページを参照ください。

構築したCI環境の概要

構築したCI環境の概要は以下の通りです。

CI環境の全体像

今回構築したCI環境では、GitLabにプッシュしたコミットにDockerfileの更新が含まれる場合のみ、更新されたDockerfileを基にビルドされたDockerイメージがプライベートレジストリに格納されます。これにより、コンテナを利用するためのイメージの管理やテストが効率良く行えます。

JenkinsとGitLabは連携済みであることを前提とします。JenkinsとGitLabの連携方法については以下の記事を参照ください。

Jenkinsfileの作成と実行

以下のJenkinsfileを用いて、このワークフローを実装しました。各ステージの when { changeset "Dockerfile" }により、GitLabのリポジトリのルートに格納しているファイルのうちDockerfileに変更があった場合のみ、各ステージに記述しているステップを実行します。

pipeline {
    agent any
    environment {
      DOCKER_IMAGE = "my-app"
      DOCKER_TAG = "0.0.3"
      REGISTRY = "localhost:5000"
    }

    stages {
        stage('Build Docker Image') {
            when {
              changeset "Dockerfile"
            }
            steps {
              sh "docker image build -t ${DOCKER_IMAGE}:${DOCKER_TAG} ."
            }
        }
        stage('Test') {
            when {
              changeset "Dockerfile"
            }
            steps {
                sh "docker container run --rm ${DOCKER_IMAGE}:${DOCKER_TAG} echo 'Test passed!'"
            }
        }
        stage('Deploy') {
            when {
              changeset "Dockerfile"
            }
            steps {
              sh """
                docker tag ${DOCKER_IMAGE}:${DOCKER_TAG} ${REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG}
                docker push ${REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG}
              """
            }
        }
    }
    post {
      always {
        sh "docker rmi ${DOCKER_IMAGE}:${DOCKER_TAG} ${REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG} || true"
      }
    }
}

GitLabのリポジトリに何らかの変更を加えてパイプラインを自動実行します。以下のように、Dockerfileに更新がない場合とある場合でパイプラインの実行内容が異なり、Dockerfileに変更がある場合にはプライベートレジストリに更新されたDockerイメージが格納されたことが分かります。
ここでは分かりやすくするため、予めプライベートレジストリにmy-app:0.0.1, my-app:0.0.2イメージを格納しており、Dockerfileを修正してパイプラインを実行し、新たにmy-app:0.0.3イメージを格納しています。

まとめ

Jenkinsを使ってDockerのプライベートレジストリを利用する方法を試し、Dockerイメージをビルドしてプライベートレジストリに格納する仕組みを構築しました。これにより、コンテナを利用するためのイメージの管理やテストが効率良く行えるようになります。DockerのプライベートレジストリをJenkinsと連携して利用してみたい方は、ぜひ参考にしてください。

開発基盤構築ソリューションチームではCI環境の構築を承っています。オンプレミスやクラウドだけでなく、コンテナを利用したい場合でもサポートできますので、ぜひお気軽にお問い合わせください。

By yoneta