コンテナイメージのビルドとコンテナレジストリへのプッシュ

コンテナイメージをビルドしてプッシュする前に、コンテナレジストリで認証を行う必要があります。

Dockerコマンドの使用

Dockerコマンドを使用してコンテナイメージをビルドし、コンテナレジストリにプッシュすることができます:

  1. コンテナレジストリで認証します。
  2. ビルドまたはプッシュするDockerコマンドを実行します。例えば

    • ビルドするには

       docker build -t registry.example.com/group/project/image .
      
    • 押すこと

       docker push registry.example.com/group/project/image
      

.gitlab-ci.yml ファイルの設定

.gitlab-ci.yml ファイルを設定して、コンテナイメージをビルドし、コンテナレジストリにプッシュすることができます。

  • 複数のジョブで認証が必要な場合は、認証コマンドをbefore_script.
  • ビルドする前に、docker build --pull を使ってベースイメージの変更をフェッチしてください。少し時間がかかりますが、イメージが最新であることを保証します。
  • docker run の前に、docker pull を明示的に実行し、ビルドされたばかりのイメージを取得します。このステップは、画像をローカルにキャッシュする複数のランナーを使用している場合に特に重要です。

    GitのSHAをimageタグに使えば、それぞれのジョブは一意であり、古い画像を持つことはありません。しかし、依存関係が変更された後でコミットをリビルドすると、古いイメージになる可能性があります。

  • 複数のジョブが同時に実行される可能性があるので、latest タグに直接ビルドしないでください。

GitLab CI/CDを使いましょう。

GitLab CI/CDを使ってコンテナイメージをビルドし、コンテナレジストリにプッシュすることができます。CI/CD を使って、作成したコンテナイメージからプロジェクトをテスト、ビルド、デプロイすることができます。

コンテナレジストリからDocker-in-Dockerコンテナイメージを使用します。

Docker-in-Dockerには独自のコンテナイメージを使用できます。

  1. Docker-in-Dockerのセットアップ。
  2. レジストリを指すようにimageservice を更新します。
  3. サービス・エイリアスを追加します。

.gitlab-ci.yml はこのようになります:

build:
  image: $CI_REGISTRY/group/project/docker:20.10.16
  services:
    - name: $CI_REGISTRY/group/project/docker:20.10.16-dind
      alias: docker
  stage: build
  script:
    - docker build -t my-docker-image .
    - docker run my-docker-image /script/to/run/tests

サービス・エイリアスの設定を忘れると、コンテナ・イメージはdind サービスを見つけることができず、次のようなエラーが表示されます:

error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host

依存プロキシを使用してDocker-in-Dockerコンテナイメージを使用します。

Dependency Proxyを使えば、独自のコンテナイメージを利用できます。

  1. Docker-in-Dockerのセットアップ。
  2. レジストリを指すようにimageservice を更新します。
  3. サービス・エイリアスを追加します。

.gitlab-ci.yml はこのようになります:

build:
  image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:20.10.16
  services:
    - name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:18.09.7-dind
      alias: docker
  stage: build
  script:
    - docker build -t my-docker-image .
    - docker run my-docker-image /script/to/run/tests

サービス・エイリアスの設定を忘れると、コンテナ・イメージはdind サービスを見つけることができず、次のようなエラーが表示されます:

error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host

GitLab CI/CDを使ったコンテナレジストリの例

RunnerでDocker-in-Dockerを使用している場合、.gitlab-ci.yml ファイルは以下のようになります:

build:
  image: docker:20.10.16
  stage: build
  services:
    - docker:20.10.16-dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $CI_REGISTRY/group/project/image:latest .
    - docker push $CI_REGISTRY/group/project/image:latest

.gitlab-ci.yml ファイルではCI/CD 変数を使用できます。例えば

build:
  image: docker:20.10.16
  stage: build
  services:
    - docker:20.10.16-dind
  variables:
    IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG

この例では、$CI_REGISTRY_IMAGE はこのプロジェクトに関連付けられているレジストリのアドレスに解決されます。$CI_COMMIT_REF_NAME はブランチまたはタグ名に解決され、スラッシュを含むことができます。画像タグにはスラッシュを含めることはできません。画像タグには$CI_COMMIT_REF_SLUG を使用します。$CI_REGISTRY_IMAGE$CI_COMMIT_REF_NAME を組み合わせて変数$IMAGE_TAGを宣言すると、script セクションでの入力の手間を省くことができます。

この例では、タスクを4つのパイプラインステージに分割し、並行して実行される2つのテストを含みます。build はコンテナレジストリに保存され、後続のステージで使用され、必要なときにコンテナイメージをダウンロードします。main への変更もlatest としてタグ付けされ、アプリケーション固有のデプロイスクリプトを使用してデプロイされます:

default:
  image: docker:20.10.16
  services:
    - docker:20.10.16-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

stages:
  - build
  - test
  - release
  - deploy

variables:
  # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
  DOCKER_HOST: tcp://docker:2376
  DOCKER_TLS_CERTDIR: "/certs"
  CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
  CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest

build:
  stage: build
  script:
    - docker build --pull -t $CONTAINER_TEST_IMAGE .
    - docker push $CONTAINER_TEST_IMAGE

test1:
  stage: test
  script:
    - docker pull $CONTAINER_TEST_IMAGE
    - docker run $CONTAINER_TEST_IMAGE /script/to/run/tests

test2:
  stage: test
  script:
    - docker pull $CONTAINER_TEST_IMAGE
    - docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test

release-image:
  stage: release
  script:
    - docker pull $CONTAINER_TEST_IMAGE
    - docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE
    - docker push $CONTAINER_RELEASE_IMAGE
  only:
    - main

deploy:
  stage: deploy
  script:
    - ./deploy.sh
  only:
    - main
  environment: production
note
この例では、docker pull を明示的に呼び出しています。image: を使用してコンテナイメージを暗黙的にプルし、DockerまたはKubernetes のエクゼキュータを使用する場合は、次のように設定します。 pull_policyalwaysに設定されていることを確認してください。