GNU/Linux >> Linux の 問題 >  >> Panels >> Docker

GitLabCIパイプラインでDockerイメージを構築する方法

CIパイプラインの一般的なユースケースの1つは、アプリケーションのデプロイに使用するDockerイメージを構築することです。 GitLab CIは、統合されたプルプロキシサービスをサポートしているため、これに最適です。つまり、より高速なパイプラインと、ビルドされたイメージを保存するための組み込みのレジストリがサポートされています。

このガイドでは、上記の両方の機能を使用するDockerビルドを設定する方法を説明します。実行する必要のある手順は、パイプラインに使用するGitLabRunnerエグゼキューターのタイプによってわずかに異なります。以下では、ShellとDockerのエグゼキュータについて説明します。

シェルエグゼキューターを使用したビルド

Shell executorを使用している場合は、ランナーをホストするマシンにDockerがインストールされていることを確認してください。エグゼキュータは、dockerを使用して通常のシェルコマンドを実行することで機能します ランナーのホスト上のバイナリ。

イメージをビルドするプロジェクトのGitリポジトリに移動します。 .gitlab-ci.ymlを作成します リポジトリのルートにあるファイル。このファイルは、プロジェクトに変更をプッシュしたときに実行されるGitLabCIパイプラインを定義します。

次のコンテンツをファイルに追加します:

stages:
  - build

docker_build:
  stage: build
  script:
    - docker build -t example.com/example-image:latest .
    - docker push example.com/example-image:latest

この単純な構成は、パイプラインを利用したイメージビルドの基本を示すのに十分です。 GitLabはGitリポジトリをビルド環境に自動的に複製するため、docker buildを実行します プロジェクトのDockerfileを使用します リポジトリのコンテンツをビルドコンテキストとして利用できるようにします。

ビルドが完了したら、docker pushを実行できます レジストリへの画像。それ以外の場合は、ビルドを実行したローカルのDockerインストールでのみ使用できます。プライベートレジストリを使用している場合は、docker loginを実行します 最初に適切な認証の詳細を提供します:

script:
  - docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD

GitLabWebUIで[設定]>[CI/ CD]> [変数]に移動して、2つのクレデンシャル変数の値を定義します。青い[変数の追加]ボタンをクリックして、新しい変数を作成し、値を割り当てます。 GitLabは、これらの変数を、ジョブの実行に使用されるシェル環境で使用できるようにします。

DockerExecutorを使用したビルド

GitLab RunnerのDockerエグゼキューターは、通常、各ジョブに完全にクリーンな環境を提供するために使用されます。ジョブは分離されたコンテナで実行されるため、docker Runnerホストのバイナリにアクセスできなくなります。

Docker executorは、イメージをビルドするための2つの可能な戦略を提供します。Docker-in-Dockerを使用するか、ホストのDockerソケットをRunnerのビルド環境にバインドします。次に、公式のDockerコンテナイメージをジョブのイメージとして使用して、dockerを作成します。 CIスクリプトで使用可能なコマンド。

Docker-in-Docker

Docker-in-Docker(DinD)を使用してイメージを構築すると、ジョブごとに完全に分離された環境が得られます。ビルドを実行するDockerプロセスは、GitLabRunnerがCIジョブを実行するためにホスト上に作成するコンテナーの子になります。

DinDを使用するには、特権モードを有効にしてGitLabRunnerDockerエグゼキューターを登録する必要があります。 --docker-privilegedを追加します ランナーを登録するときにフラグを立てる:

sudo gitlab-runner register -n 
  --url https://example.com 
  --registration-token $GITLAB_REGISTRATION_TOKEN 
  --executor docker 
  --description "Docker Runner" 
  --docker-image "docker:20.10" 
  --docker-volumes "/certs/client" 
  --docker-privileged

CIパイプライン内に、docker:dindを追加します サービスとしての画像。これにより、Dockerはジョブのイメージにリンクされた個別のイメージとして利用できるようになります。 dockerを使用できるようになります docker:dindのDockerインスタンスを使用してイメージをビルドするコマンド コンテナ。

services:
  - docker:dind

docker_build:
  stage: build
  image: docker:latest
  script:
    - docker build -t example-image:latest .

DinDを使用すると、相互に影響を与えたり、ホストに影響を与えたりすることのない、完全に分離されたビルドが得られます。主な欠点は、より複雑なキャッシュ動作です。各ジョブは、以前に構築されたレイヤーにアクセスできない新しい環境を取得します。ビルドする前に以前のバージョンのイメージをプルしてから、--cache-fromを使用することで、これに部分的に対処できます。 プルされたイメージのレイヤーをキャッシュソースとして使用できるようにするためのビルドフラグ:

docker_build:
  stage: build
  image: docker:latest
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:latest .
ソケットバインドマウント

Docker executorを使用している場合は、ホストのDockerソケットをジョブの環境にマウントすることもできます。これにより、シームレスなキャッシュが可能になり、docker:dindを追加する必要がなくなります。 CI構成へのサービス。

これを設定するには、ランナーをdocker-volumesに登録します ホストのDockerソケットを/var/run/docker.sockにバインドするフラグ ジョブコンテナ内:

sudo gitlab-runner register -n 
  --url https://example.com 
  --registration-token $GITLAB_REGISTRATION_TOKEN 
  --executor docker 
  --description "Docker Runner" 
  --docker-image "docker:20.10" 
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock

dockerで実行されるジョブ 画像はdockerを使用できるようになります 通常どおりバイナリ。操作は実際にはホストマシンで行われ、子ではなくジョブのコンテナの兄弟になります。

これは、ホストのDockerインストールでシェルエグゼキュータを使用するのと実質的に同じです。イメージはホスト上に存在し、通常のdocker buildのシームレスな使用を容易にします レイヤーキャッシング。

このアプローチは、パフォーマンスの向上、構成の削減、およびDinDの制限のいずれにもつながる可能性がありますが、独自の問題があります。これらの中で最も顕著なのはセキュリティへの影響です。ジョブはRunnerホスト上で任意のDockerコマンドを実行する可能性があるため、GitLabインスタンス内の悪意のあるプロジェクトがdocker run -it malicious-image:latestを実行する可能性があります またはdocker rm -f $(docker ps -a) 壊滅的な結果をもたらします。

GitLabは、ジョブが同時に実行されるときにソケットバインディングが問題を引き起こす可能性があることにも注意しています。これは、特定の名前で作成されているコンテナに依存している場合に発生します。ジョブの2つのインスタンスが並行して実行される場合、コンテナ名はホストにすでに存在するため、2番目のインスタンスは失敗します。

これらの問題のいずれかが厄介になると予想される場合は、代わりにDinDの使用を検討する必要があります。 DinDは一般的には推奨されなくなりましたが、同時CIジョブを実行する公開されているGitLabインスタンスの方が理にかなっています。

画像をGitLabのレジストリにプッシュする

GitLabプロジェクトには、画像の保存に使用できる統合レジストリのオプションがあります。プロジェクトのサイドバーで[パッケージとレジストリ]>[コンテナレジストリ]に移動すると、レジストリのコンテンツを表示できます。このリンクが表示されない場合は、[設定]>[一般]>[可視性、プロジェクト、機能、権限]に移動し、[コンテナレジストリ]トグルを有効にしてレジストリを有効にします。

GitLabは、CIジョブに環境変数を自動的に設定し、プロジェクトのコンテナーレジストリを参照できるようにします。 scriptを調整します レジストリにログインして画像をプッシュするセクション:

script:
  - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
  - docker build -t $CI_REGISTRY_IMAGE:latest .
  - docker push $CI_REGISTRY_IMAGE:latest

GitLabは、CIジョブごとに安全なクレデンシャルのセットを生成します。 $CI_JOB_TOKEN 環境変数には、ジョブがgitlab-ci-tokenとしてレジストリに接続するために使用できるアクセストークンが含まれます。 ユーザー。レジストリサーバーのURLは、$CI_REGISTRYとして利用できます。 。

最後の変数、$CI_REGISTRY_IMAGE 、プロジェクトのコンテナレジストリへの完全なパスを提供します。これは、画像タグに適したベースです。この変数を拡張して、$CI_REGISTRY_IMAGE/production/api:latestなどのサブリポジトリを作成できます。 。

他のDockerクライアントは、アクセストークンを使用して認証することにより、レジストリからイメージをプルできます。これらは、プロジェクトの[設定]>[アクセストークン]画面で生成できます。 read_registryを追加します スコープを設定し、表示されたクレデンシャルを使用してdocker login プロジェクトのレジストリに追加します。

GitLabの依存関係プロキシの使用

GitLabのDependencyProxyは、DockerHubからプルするアップストリームイメージのキャッシュレイヤーを提供します。画像が実際に変更されたときにのみ画像のコンテンツを取得することで、DockerHubのレート制限内にとどまることができます。これにより、ビルドのパフォーマンスも向上します。

依存関係プロキシは、[設定]>[パッケージとレジストリ]>[依存関係プロキシ]に移動することで、GitLabグループレベルでアクティブ化されます。有効にしたら、.gitlab-ci.ymlで画像参照のプレフィックスを付けます $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIXのファイル プロキシを介してそれらをプルするには:

docker_build:
  stage: build
  image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:latest
  services:
    - name: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:dind
      alias: docker

これですべてです。 GitLab Runnerは依存関係プロキシレジストリに自動的にログインするため、手動で資格情報を提供する必要はありません。

GitLabは画像をキャッシュするようになり、パフォーマンスが向上し、ネットワークの停止に対する回復力が向上します。 servicesに注意してください 定義も調整する必要がありました。環境変数は以前に使用したインラインフォームでは機能しないため、画像全体のname 指定する必要があり、次にコマンドalias scriptで参照する セクション。

これで、ジョブステージで直接使用されるイメージのプロキシが設定されましたが、Dockerfileでベースイメージのサポートを追加するにはさらに作業が必要です。 構築する。このような通常の指示はプロキシを通過しません:

FROM ubuntu:latest

この最後の部分を追加するには、Dockerのビルド引数を使用して、Dockerfileをステップスルーするときに依存関係プロキシURLを使用できるようにします。

ARG GITLAB_DEPENDENCY_PROXY
FROM ${GITLAB_DEPENDENCY_PROXY}/ubuntu:latest

次に、docker buildを変更します 変数の値を定義するコマンド:

script:
  >
    - docker build 
        --build-arg GITLAB_DEPENDENCY_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX} 
        -t example-image:latest .

これで、ベースイメージも依存関係プロキシを介してプルされます。

概要

Dockerイメージビルドは、GitLabCIパイプラインに簡単に統合できます。ランナーの初期構成後、docker build およびdocker push ジョブのscriptのコマンド Dockerfileを使用して画像を作成するために必要なのはセクションだけです。 リポジトリ内。 GitLabの組み込みコンテナレジストリは、プロジェクトの画像用のプライベートストレージを提供します。

基本的なビルドに加えて、GitLabの依存関係プロキシを統合して、パフォーマンスを加速し、DockerHubのレート制限に達しないようにする価値があります。また、選択した方法で信頼できないプロジェクトがRunnerホストでコマンドを実行できるかどうかを評価して、インストールのセキュリティを確認する必要があります。独自の問題がありますが、Docker-in-Dockerは、GitLabインスタンスが一般にアクセス可能であるか、大規模なユーザーベースからアクセスできる場合に最も安全なアプローチです。


Docker
  1. Dockerイメージを他の人と共有する方法

  2. Dockerイメージの概要

  3. Dockerfileを使用してカスタムDockerイメージを自動的に構築および構成する方法–パート3

  1. LinuxでDockerイメージを検索、プル、リスト、および削除する方法

  2. Anaconda Python DataScienceDockerコンテナを構築する方法

  3. Minikube でローカル docker イメージを使用するには?

  1. ホスト間でDockerイメージを移動する方法

  2. Dockerfileを使用してDockerイメージを構築する方法

  3. Dockerイメージを変更する方法