著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。

序章

GitLab は、コードリポジトリのホストを超えた強力な機能を提供するオープンソースのコラボレーションプラットフォームです。 問題の追跡、パッケージとレジストリのホスト、Wikiの保守、継続的インテグレーション(CI)および継続的デプロイメント(CD)パイプラインの設定などを行うことができます。

このチュートリアルでは、GitLabを使用して継続的デプロイパイプラインを構築します。 Dockerイメージを構築し、それをGitLabコンテナーレジストリにプッシュし、SSHを使用してサーバーにデプロイするようにパイプラインを構成します。 パイプラインは、リポジトリにプッシュされたコミットごとに実行されます。

小さな静的Webページを展開しますが、このチュートリアルの焦点はCDパイプラインの構成です。 静的なWebページは、デモンストレーションのみを目的としています。 デプロイに他のDockerイメージを使用して同じパイプライン構成を適用することもできます。

このチュートリアルを終了すると、次のサイトにアクセスできます。 http://your_server_IP 自動展開の結果については、ブラウザで。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • Ubuntu 18.04初期サーバーセットアップガイドに従ってセットアップされた1つのUbuntu18.04サーバー(sudo非rootユーザーとファイアウォールを含む)。 少なくとも1GBのRAMと1つのCPUが必要です。
  • Ubuntu18.04ガイドにDockerをインストールして使用する方法に従ってサーバーにDockerをインストールします。
  • コンテナレジストリが有効になっているGitLabインスタンスのユーザーアカウント。 公式GitLabインスタンスの無料プランは要件を満たしています。 Ubuntu 18.04ガイドにGitLabをインストールして構成する方法に従って、独自のGitLabインスタンスをホストすることもできます。

ステップ1—GitLabリポジトリを作成する

まず、GitLabプロジェクトを作成し、それにHTMLファイルを追加します。 後でHTMLファイルをNginxDockerイメージにコピーし、サーバーにデプロイします。

GitLabインスタンスにログインし、新しいプロジェクトをクリックします。

  1. 適切なプロジェクト名を付けてください。
  2. オプションで、プロジェクトの説明を追加します。
  3. 要件に応じて、可視性レベルプライベートまたはパブリックに設定してください。
  4. 最後にプロジェクトの作成をクリックします

プロジェクトの概要ページにリダイレクトされます。

HTMLファイルを作成しましょう。 プロジェクトの概要ページで、新しいファイルをクリックします。

ファイル名index.html 次のHTMLをファイル本体に追加します。

index.html
<html>
<body>
<h1>My Personal Website</h1>
</body>
</html>

ページ下部のコミット変更をクリックしてファイルを作成します。

このHTMLは、ブラウザで開いたときに個人のWebサイトを示す1つの見出しのある空白のページを生成します。

Dockerfileは、DockerがDockerイメージを構築するために使用するレシピです。 を作成しましょう Dockerfile HTMLファイルをNginxイメージにコピーします。

プロジェクトの概要ページに戻り、 + ボタンをクリックして、新しいファイルオプションを選択します。

ファイル名Dockerfile 次の手順をファイル本体に追加します。

Dockerfile
FROM nginx:1.18
COPY index.html /usr/share/nginx/html

The FROM 命令は、継承する画像を指定します。この場合、 nginx:1.18 画像。 1.18 Nginxバージョンを表す画像タグです。 The nginx:latest タグは最新のNginxリリースを参照しますが、将来的にアプリケーションが破損する可能性があるため、修正バージョンをお勧めします。

The COPY 命令はコピーします index.html にファイルする /usr/share/nginx/html Dockerイメージ内。 これは、Nginxが静的HTMLコンテンツを保存するディレクトリです。

ページ下部のコミット変更をクリックしてファイルを作成します。

次のステップでは、GitLabランナーを構成して、デプロイジョブを実行できるユーザーを制御します。

ステップ2—GitLabランナーの登録

SSH秘密鍵と接触する環境を追跡するために、サーバーをGitLabランナーとして登録します。

デプロイメントパイプラインで、SSHを使用してサーバーにログインする必要があります。 これを実現するには、SSH秘密鍵をGitLab CI / CD変数に保存します(ステップ5)。 SSH秘密鍵は、サーバーへのエントリチケットであるため、非常に機密性の高いデータです。 通常、秘密鍵は、それが生成されたシステムを離れることはありません。 通常の場合、手動でログインして展開ルーチンを実行するために、ホストマシンでSSHキーを生成してから、サーバーでSSHキーを承認します(つまり、公開キーをサーバーにコピーします)。

ここで状況が少し変わります。サーバーへの自律権限(GitLab CI / CD)アクセスを許可して、展開ルーチンを自動化する必要があります。 したがって、秘密鍵は、それが生成されたシステムを離れ、GitLabやその他の関係者に信頼を与える必要があります。 自分の秘密鍵が、自分で制御または信頼されていない環境に入ることは絶対に避けてください。

GitLabに加えて、GitLabランナーは、秘密鍵が入力されるもう1つのシステムです。 パイプラインごとに、GitLabはランナーを使用して重い作業を実行します。つまり、CI/CD構成で指定したジョブを実行します。 つまり、デプロイジョブは最終的にGitLabランナーで実行されるため、SSHを使用してサーバーにログインできるように秘密鍵がランナーにコピーされます。

不明なGitLabランナー(たとえば、共有ランナー)を使用して展開ジョブを実行する場合、システムが秘密鍵に接触していることに気付かないでしょう。 GitLabランナーはジョブの実行後にすべてのデータをクリーンアップしますが、独自のサーバーをGitLabランナーとして登録することで、不明なシステムに秘密鍵を送信することを回避できます。 秘密鍵は、あなたが管理するサーバーにコピーされます。

サーバーにログインすることから始めます。

  1. ssh sammy@your_server_IP

インストールするために gitlab-runner サービスでは、公式のGitLabリポジトリを追加します。 インストールスクリプトをダウンロードして検査します。

  1. curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh > script.deb.sh
  2. less script.deb.sh

スクリプトの安全性に満足したら、インストーラーを実行します。

  1. sudo bash script.deb.sh

わかりにくいかもしれませんが、続行するには非rootユーザーのパスワードを入力する必要があります。 前のコマンドを実行すると、出力は次のようになります。

Output
[sudo] password for sammy: % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 5945 100 5945 0 0 8742 0 --:--:-- --:--:-- --:--:-- 8729

いつ curl コマンドが終了すると、次のメッセージが表示されます。

Output
The repository is setup! You can now install packages.

次に、 gitlab-runner サービス:

  1. sudo apt install gitlab-runner

サービスステータスを確認して、インストールを確認します。

  1. systemctl status gitlab-runner

あなたが持っているでしょう active (running) 出力:

Output
● gitlab-runner.service - GitLab Runner Loaded: loaded (/etc/systemd/system/gitlab-runner.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2020-06-01 09:01:49 UTC; 4s ago Main PID: 16653 (gitlab-runner) Tasks: 6 (limit: 1152) CGroup: /system.slice/gitlab-runner.service └─16653 /usr/lib/gitlab-runner/gitlab-runner run --working-directory /home/gitlab-runner --config /etc/gitla

ランナーを登録するには、プロジェクトトークンとGitLabURLを取得する必要があります。

  1. GitLabプロジェクトで、設定> CI / CD>ランナーに移動します。
  2. 特定のランナーを手動でセットアップするセクションには、登録トークンとGitLabURLがあります。 両方をテキストエディタにコピーします。 次のコマンドで必要になります。 それらはと呼ばれます https://your_gitlab.comproject_token.

ターミナルに戻り、プロジェクトのランナーを登録します。

  1. sudo gitlab-runner register -n --url https://your_gitlab.com --registration-token project_token --executor docker --description "Deployment Runner" --docker-image "docker:stable" --tag-list deployment --docker-privileged

コマンドオプションは次のように解釈できます。

  • -n を実行します register 非対話的にコマンドを実行します(すべてのパラメーターをコマンドオプションとして指定します)。
  • --url GitLabのランナーページからコピーしたGitLabURLです。
  • --registration-token GitLabのランナーページからコピーしたトークンです。
  • --executor エグゼキュータタイプです。 docker Dockerコンテナ内の各CI/CDジョブを実行します( GitLabのエグゼキュータに関するドキュメントを参照)。
  • --description はランナーの説明であり、GitLabに表示されます。
  • --docker-image 明示的に指定されていない場合、CI/CDジョブで使用するデフォルトのDockerイメージです。
  • --tag-list ランナーに割り当てられたタグのリストです。 タグをパイプライン構成で使用して、CI/CDジョブの特定のランナーを選択できます。 The deployment タグを使用すると、この特定のランナーを参照してデプロイメントジョブを実行できます。
  • --docker-privileged CI/CDジョブごとに作成されたDockerコンテナを特権モードで実行します。 特権コンテナーは、ホストマシン上のすべてのデバイスにアクセスでき、コンテナーの外部で実行されているプロセスとほぼ同じようにホストにアクセスできます(ランタイム特権とLinux機能に関するDockerのドキュメントを参照)。 特権モードで実行する理由は、Docker-in-Docker( did )を使用してCI/CDパイプラインにDockerイメージを構築できるようにするためです。 コンテナに必要な最小要件を与えることをお勧めします。 Docker-in-Dockerを使用するには、特権モードで実行する必要があります。 この特定のプロジェクトにのみランナーを登録したことに注意してください。このプロジェクトでは、特権コンテナーで実行されるコマンドを制御できます。

実行後 gitlab-runner register コマンドを実行すると、次の出力が表示されます。

Output
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

GitLabの設定>CI / CD > ランナーに移動して、登録プロセスを確認します。ここに、登録済みのランナーが表示されます。

次のステップでは、デプロイメントユーザーを作成します。

ステップ3—デプロイメントユーザーの作成

展開タスク専用のユーザーを作成します。 後で、そのユーザーでサーバーにログインするようにCI/CDパイプラインを構成します。

サーバーで、新しいユーザーを作成します。

  1. sudo adduser deployer

ユーザー作成プロセスをガイドします。 強力なパスワードと、オプションで指定する追加のユーザー情報を入力します。 最後に、ユーザーの作成を確認します Y.

ユーザーをDockerグループに追加します。

  1. sudo usermod -aG docker deployer

これにより、deployerdocker コマンド。これは、展開を実行するために必要です。

警告: Dockerグループにユーザーを追加すると、rootユーザーと同等の権限が付与されます。 これがシステムのセキュリティにどのように影響するかについての詳細は、 Docker Daemon AttackSurfaceを参照してください。

次のステップでは、SSHキーを作成して、deployerとしてサーバーにログインできるようにします。

ステップ4—SSHキーを設定する

デプロイメントユーザー用のSSHキーを作成します。 GitLab CI / CDは後でキーを使用してサーバーにログインし、展開ルーチンを実行します。

SSHキーを生成する新しく作成されたdeployerユーザーに切り替えることから始めましょう。

  1. su deployer

ユーザーの切り替えを完了するために、deployerパスワードの入力を求められます。

次に、4096ビットのSSHキーを生成します。 の質問に答えることが重要です ssh-keygen 正しくコマンド:

  1. 最初の質問:で答える ENTER、これはキーをデフォルトの場所に保存します(このチュートリアルの残りの部分では、キーがデフォルトの場所に保存されていることを前提としています)。
  2. 2番目の質問:SSH秘密鍵(認証に使用される鍵)を保護するためのパスワードを構成します。 パスフレーズを指定すると、秘密鍵を使用するたびにパスフレーズを入力する必要があります。 一般に、パスフレーズはSSHキーに別のセキュリティレイヤーを追加します。これは良い習慣です。 秘密鍵を所持している人は、鍵を使用するためにパスフレーズも必要になります。 このチュートリアルでは、CI / CDパイプラインが非対話的に実行されるため、パスフレーズを入力できないため、パスフレーズが空であることが重要です。

要約すると、次のコマンドを実行し、両方の質問を次のように確認します。 ENTER 4096ビットのSSHキーを作成し、空のパスフレーズを使用してデフォルトの場所に保存するには、次のようにします。

  1. ssh-keygen -b 4096

deployer ユーザーのSSHキーを承認するには、公開キーをに追加する必要があります authorized_keys ファイル:

  1. cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

~ Linuxのユーザーホームの略です。 The cat プログラムはファイルの内容を出力します。 ここでは、 >> の出力をリダイレクトする演算子 cat に追加します authorized_keys ファイル。

このステップでは、CI/CDパイプラインがログインしてアプリケーションをデプロイするためのSSHキーペアを作成しました。 次に、秘密鍵をGitLabに保存して、パイプラインプロセス中にアクセスできるようにします。

ステップ5—秘密鍵をGitLab CI/CD変数に保存する

SSH秘密鍵をGitLabCI/ CDファイル変数に保存して、パイプラインが鍵を使用してサーバーにログインできるようにします。

GitLabがCI/CDパイプラインを作成すると、すべての変数が対応するランナーに送信され、ジョブの期間中、変数は環境変数として設定されます。 特に、 file 変数の値はファイルに保存され、環境変数にはこのファイルへのパスが含まれます。

変数セクションにいる間に、サーバーIPとサーバーユーザーの変数も追加します。これにより、ログイン先のサーバーとユーザーについてパイプラインに通知されます。

SSH秘密鍵を表示することから始めます。

  1. cat ~/.ssh/id_rsa

出力をクリップボードにコピーします。 後に必ず改行を追加してください -----END RSA PRIVATE KEY-----:

〜/ .ssh / id_rsa
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----


次に、GitLabプロジェクトの設定> CI / CD > 変数に移動し、変数の追加をクリックします。 次のようにフォームに記入します。

  • 鍵: ID_RSA
  • 値:クリップボードからSSH秘密鍵を貼り付けます(最後の改行を含む)。
  • タイプ:ファイル
  • 環境範囲:すべて(デフォルト)
  • 保護変数:チェック済み
  • マスク変数:チェックなし

注:正規表現の要件を満たしていないため、変数をマスクできません(マスクされた変数に関するGitLabのドキュメントを参照)。 ただし、秘密鍵はコンソールログに表示されないため、マスキングは廃止されます。

秘密鍵を含むファイルが各CI/CDジョブのランナーに作成され、そのパスがに保存されます。 $ID_RSA 環境変数。

サーバーIPを使用して別の変数を作成します。 変数の追加をクリックし、次のようにフォームに入力します。

  • 鍵: SERVER_IP
  • 価値: your_server_IP
  • タイプ:変数
  • 環境範囲:すべて(デフォルト)
  • 保護変数:チェック済み
  • マスク変数:チェック済み

最後に、ログインユーザーで変数を作成します。 変数の追加をクリックし、次のようにフォームに入力します。

  • 鍵: SERVER_USER
  • 価値: deployer
  • タイプ:変数
  • 環境範囲:すべて(デフォルト)
  • 保護変数:チェック済み
  • マスク変数:チェック済み

これで、秘密鍵がGitLab CI / CD変数に保存されました。これにより、パイプラインの実行中に鍵を使用できるようになります。 次のステップでは、CI/CDパイプラインの構成に進みます。

ステップ6—設定 .gitlab-ci.yml ファイル

GitLab CI/CDパイプラインを構成します。 パイプラインはDockerイメージを構築し、それをコンテナーレジストリにプッシュします。 GitLabは、プロジェクトごとにコンテナレジストリを提供します。 次の場所に移動すると、コンテナレジストリを調べることができます。 パッケージとレジストリ >> コンテナレジストリ GitLabプロジェクトで(詳細は GitLabのコンテナレジストリドキュメント 。)パイプラインの最後のステップは、サーバーにログインし、最新のDockerイメージをプルし、古いコンテナーを削除して、新しいコンテナーを開始することです。

次に、を作成します .gitlab-ci.yml パイプライン構成を含むファイル。 GitLabで、プロジェクトの概要ページに移動し、 + ボタンをクリックして、新しいファイルを選択します。 次に、ファイル名をに設定します .gitlab-ci.yml.

(または、リポジトリのクローンを作成して、以下のすべての変更を行うことができます。 .gitlab-ci.yml ローカルマシンで、コミットしてリモートリポジトリにプッシュします。)

開始するには、以下を追加します。

.gitlab-ci.yml
stages:
  - publish
  - deploy

各ジョブはステージに割り当てられます。 同じステージに割り当てられたジョブは並行して実行されます(十分な数のランナーが利用可能な場合)。 ステージは指定された順序で実行されます。 ここでは、 publish ステージが最初になり、 deploy ステージセカンド。 後続のステージは、前のステージが正常に終了したとき(つまり、すべてのジョブが合格したとき)にのみ開始されます。 芸名は任意に選ぶことができます。

このCD構成を、アプリをテストおよびビルドする既存のCIパイプラインと組み合わせる場合は、 publishdeploy テストに合格した場合にのみ展開が行われるように、既存のステージの次のステージ。

これに続いて、これをあなたの .gitlab-ci.yml ファイル:

.gitlab-ci.yml
. . .
variables:
  TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
  TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA

変数セクションは、ジョブのコンテキストで使用できる環境変数を定義します script セクション。 これらの変数は、通常のLinux環境変数として使用できます。 つまり、次のようなドル記号を前に付けることで、スクリプトでそれらを参照できます。 $TAG_LATEST. GitLabは、ジョブごとにいくつかの定義済み変数を作成し、ブランチ名やジョブが処理しているコミットハッシュなどのコンテキスト固有の情報を提供します(事前定義変数の詳細をご覧ください)。 ここでは、事前定義された変数から2つの環境変数を作成します。 それらは以下を表します:

  • CI_REGISTRY_IMAGE:特定のプロジェクトに関連付けられているコンテナレジストリのURLを表します。 このURLはGitLabインスタンスによって異なります。 たとえば、 gitlab.com プロジェクトのレジストリURLは、次のパターンに従います。 registry.gitlab.com/your_user/your_project. ただし、GitLabがこの変数を提供するため、正確なURLを知る必要はありません。
  • CI_COMMIT_REF_NAME:プロジェクトがビルドされるブランチまたはタグの名前。
  • CI_COMMIT_SHORT_SHA:プロジェクトがビルドされるコミットリビジョンの最初の8文字。

両方の変数は事前定義された変数で構成されており、Dockerイメージにタグを付けるために使用されます。

TAG_LATEST 追加します latest 画像にタグを付けます。 これは、常に最新のリリースを表すタグを提供するための一般的な戦略です。 展開ごとに、 latest イメージは、新しくビルドされたDockerイメージを使用してコンテナレジストリでオーバーライドされます。

TAG_COMMIT一方、デプロイされているコミットSHAの最初の8文字をイメージタグとして使用することで、コミットごとに一意のDockerイメージを作成します。 Dockerイメージの履歴をGitコミットの粒度まで追跡できるようになります。 これは、展開に欠陥がある場合に古いバージョンのコードをすばやく展開できるため、継続的な展開を行う場合の一般的な手法です。

次の手順で説明するように、デプロイメントを古いGitリビジョンにロールバックするプロセスは、GitLabで直接実行できます。

$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME Dockerイメージのベース名を指定します。 GitLabのドキュメントによると、Dockerイメージ名は次のスキームに従う必要があります。

image name scheme
<registry URL>/<namespace>/<project>/<image>

$CI_REGISTRY_IMAGE を表します <registry URL>/<namespace>/<project> これはプロジェクトのレジストリルートであるため、一部であり必須です。 $CI_COMMIT_REF_NAME オプションですが、さまざまなブランチのDockerイメージをホストするのに役立ちます。 このチュートリアルでは、1つのブランチのみを操作しますが、拡張可能な構造を構築することをお勧めします。 一般に、GitLabでサポートされているイメージリポジトリ名には次の3つのレベルがあります。

repository name levels
registry.example.com/group/project:some-tag registry.example.com/group/project/image:latest registry.example.com/group/project/my/image:rc1

あなたのための TAG_COMMIT 2番目のオプションを使用した変数 image ブランチ名に置き換えられます。

次に、以下を追加します .gitlab-ci.yml ファイル:

.gitlab-ci.yml
. . .
publish:
  image: docker:latest
  stage: publish
  services:
    - docker:dind
  script:
    - docker build -t $TAG_COMMIT -t $TAG_LATEST .
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker push $TAG_COMMIT
    - docker push $TAG_LATEST

The publish セクションは、CI/CD構成の最初のジョブです。 それを分解しましょう:

  • image このジョブに使用するDockerイメージです。 GitLabランナーは、ジョブごとにDockerコンテナーを作成し、このコンテナー内でスクリプトを実行します。 docker:latest 画像は、 docker コマンドが利用可能になります。
  • stage ジョブをに割り当てます publish ステージ。
  • services Docker-in-Dockerを指定します— dind サービス。 これが、GitLabランナーを特権モードで登録した理由です。

のスクリプトセクション publish jobは、このジョブに対して実行するシェルコマンドを指定します。 これらのコマンドが実行されると、作業ディレクトリはリポジトリルートに設定されます。

  • docker build ...:に基づいてDockerイメージを構築します Dockerfile 変数セクションで定義された最新のコミットタグでタグ付けします。
  • docker login ...:Dockerをプロジェクトのコンテナレジストリにログインします。 事前定義された変数を使用します $CI_BUILD_TOKEN 認証トークンとして。 GitLabはトークンを生成し、ジョブの存続期間中有効なままになります。
  • docker push ...:両方のイメージタグをコンテナレジストリにプッシュします。

これに続いて、 deploy あなたへの仕事 .gitlab-ci.yml:

.gitlab-ci.yml
. . .
deploy:
  image: alpine:latest
  stage: deploy
  tags:
    - deployment
  script:
    - chmod og= $ID_RSA
    - apk update && apk add openssh-client
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no [email protected]$SERVER_IP "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no [email protected]$SERVER_IP "docker pull $TAG_COMMIT"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no [email protected]$SERVER_IP "docker container rm -f my-app || true"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no [email protected]$SERVER_IP "docker run -d -p 80:80 --name my-app $TAG_COMMIT"

Alpineは軽量Linuxディストリビューションであり、ここではDockerイメージとして十分です。 あなたは仕事をに割り当てます deploy ステージ。 デプロイメントタグは、タグ付けされたランナーでジョブが実行されることを保証します deployment、ステップ2で構成したランナーなど。

The script のセクション deploy ジョブは2つの構成コマンドで始まります。

  • chmod og= $ID_RSAgroupおよびothersのすべてのアクセス許可を秘密鍵から取り消して、所有者のみが使用できるようにします。 これは要件です。そうでない場合、SSHは秘密鍵の操作を拒否します。
  • apk update && apk add openssh-client:Alpineのパッケージマネージャー(apk)を更新し、 openssh-client、を提供します ssh 指図。

4連続 ssh コマンドが続きます。 それぞれのパターンは次のとおりです。

ssh connect pattern for all deployment commands
ssh -i $ID_RSA -o StrictHostKeyChecking=no [email protected]$SERVER_IP "command"

それぞれに ssh 実行しているステートメント command リモートサーバー上。 そのためには、秘密鍵を使用して認証します。

オプションは次のとおりです。

  • -i IDファイルの略で、 $ID_RSA 秘密鍵ファイルへのパスを含むGitLab変数です。
  • -o StrictHostKeyChecking=no リモートホストを信頼するかどうかにかかわらず、質問をバイパスするようにしてください。 この質問は、パイプラインなどの非対話型のコンテキストでは回答できません。
  • $SERVER_USER$SERVER_IP 手順5で作成したGitLab変数です。 SSH接続のリモートホストとログインユーザーを指定します。
  • command リモートホストで実行されます。

展開は、最終的にサーバーで次の4つのコマンドを実行することによって行われます。

  1. docker login ...:Dockerをコンテナレジストリにログインします。
  2. docker pull ...:コンテナレジストリから最新のイメージを取得します。
  3. docker container rm ...:既存のコンテナが存在する場合は削除します。 || true 名前で実行されているコンテナがなかった場合でも、終了コードが常に成功することを確認します my-app. これにより、コンテナーが存在しない場合(たとえば、最初のデプロイメントの場合)にパイプラインを中断することなく、 deleteifexistsルーチンが保証されます。
  4. docker run ...:レジストリからの最新のイメージを使用して、新しいコンテナを開始します。 コンテナには名前が付けられます my-app. ポート 80 ホスト上のポートにバインドされます 80 コンテナの(順序は -p host:container). -d コンテナをデタッチモードで開始します。そうしないと、コマンドが終了するのを待ってパイプラインがスタックします。

注:コマンドを実行するGitLabランナーがまったく同じサーバーであることを考えると、SSHを使用してサーバー上でこれらのコマンドを実行するのは奇妙に思えるかもしれません。 ただし、ランナーはDockerコンテナーでコマンドを実行するため、SSHを使用せずにコマンドを実行する場合は、サーバーではなくコンテナー内にデプロイする必要があるため、必須です。 Dockerをランナーエグゼキューターとして使用する代わりに、シェルエグゼキューターを使用してホスト自体でコマンドを実行できると主張する人もいるかもしれません。 ただし、これによりパイプラインに制約が生じます。つまり、ランナーはデプロイ先のサーバーと同じサーバーである必要があります。 ある日、アプリケーションを別のサーバーに移行したり、別のランナーサーバーを使用したりする可能性があるため、これは持続可能で拡張可能なソリューションではありません。 いずれにせよ、SSHを使用して展開コマンドを実行することは理にかなっていますが、それは技術的または移行関連の理由による場合があります。

これをあなたのデプロイメントジョブに追加して先に進みましょう .gitlab-ci.yml:

.gitlab-ci.yml
. . .
deploy:
. . .
  environment:
    name: production
    url: http://your_server_IP
  only:
    - master

GitLab環境を使用すると、GitLab内のデプロイを制御できます。 操作>環境に移動すると、GitLabプロジェクトの環境を調べることができます。 パイプラインがまだ終了していない場合、これまでのところ展開が行われていないため、利用可能な環境はありません。

パイプラインジョブが environment セクションでは、GitLabは特定の環境のデプロイメントを作成します(ここでは production)ジョブが正常に終了するたび。 これにより、GitLab CI/CDによって作成されたすべてのデプロイメントをトレースできます。 デプロイメントごとに、関連するコミットとそれが作成されたブランチを確認できます。

古いバージョンのソフトウェアにロールバックできる再展開に使用できるボタンもあります。 で指定されたURL environment 展開の表示ボタンをクリックすると、セクションが開きます。

唯一のセクションは、ジョブが実行されるブランチとタグの名前を定義します。 デフォルトでは、GitLabはリポジトリへのプッシュごとにパイプラインを開始し、すべてのジョブを実行します( .gitlab-ci.yml ファイルが存在しています)。 The only セクションは、ジョブの実行を特定のブランチ/タグに制限する1つのオプションです。 ここでは、の展開ジョブを実行します master ブランチのみ。 ジョブを実行するかどうかに関するより複雑なルールを定義するには、rules構文を参照してください。

注: 2020年10月、GitHubはデフォルトブランチの命名規則からに変更しました。 mastermain. GitLabや一般的な開発者コミュニティなどの他のプロバイダーは、このアプローチに従い始めています。 用語 master このチュートリアルでは、ブランチは、別の名前を持つ可能性のあるデフォルトのブランチを示すために使用されます。

あなたの完全な .gitlab-ci.yml ファイルは次のようになります。

.gitlab-ci.yml
stages:
  - publish
  - deploy

variables:
  TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
  TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA

publish:
  image: docker:latest
  stage: publish
  services:
    - docker:dind
  script:
    - docker build -t $TAG_COMMIT -t $TAG_LATEST .
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker push $TAG_COMMIT
    - docker push $TAG_LATEST

deploy:
  image: alpine:latest
  stage: deploy
  tags:
    - deployment
  script:
    - chmod og= $ID_RSA
    - apk update && apk add openssh-client
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no [email protected]$SERVER_IP "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no [email protected]$SERVER_IP "docker pull $TAG_COMMIT"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no [email protected]$SERVER_IP "docker container rm -f my-app || true"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no [email protected]$SERVER_IP "docker run -d -p 80:80 --name my-app $TAG_COMMIT"
  environment:
    name: production
    url: http://your_server_IP
  only:
    - master

最後に、GitLabのページの下部にあるコミット変更をクリックして、 .gitlab-ci.yml ファイル。 または、Gitリポジトリのクローンをローカルに作成したら、ファイルをコミットしてリモートにプッシュします。

Dockerイメージを構築してサーバーにデプロイするためのGitLabCI/CD構成を作成しました。 次のステップでは、展開を検証します。

ステップ7—展開の検証

次に、GitLabのさまざまな場所、サーバー、ブラウザーでのデプロイを検証します。

いつ .gitlab-ci.yml ファイルがリポジトリにプッシュされると、GitLabはそれを自動的に検出し、CI/CDパイプラインを開始します。 作成した時点で .gitlab-ci.yml ファイル、GitLabは最初のパイプラインを開始しました。

GitLabプロジェクトのCI/ CD > Pipelines に移動して、パイプラインのステータスを確認します。 ジョブがまだ実行中/保留中の場合は、完了するまで待ちます。 合格パイプラインに2つの緑色のチェックマークが表示され、公開およびデプロイジョブが正常に実行されたことを示します。

パイプラインを調べてみましょう。 ステータス列の合格ボタンをクリックして、パイプラインの概要ページを開きます。 次のような一般的な情報の概要が表示されます。

  • パイプライン全体の実行期間。
  • パイプラインが実行されたコミットとブランチ。
  • 関連するマージリクエスト。 担当支店のオープンマージリクエストがある場合は、ここに表示されます。
  • このパイプラインで実行されたすべてのジョブとそのステータス。

次に、 deploy ボタンをクリックして、デプロイジョブの結果ページを開きます。

ジョブの結果ページで、ジョブのスクリプトのシェル出力を確認できます。 これは、失敗したパイプラインをデバッグするときに探す場所です。 右側のサイドバーには、このジョブに追加したデプロイメントタグがあり、 DeploymentRunnerで実行されたことがわかります。

ページの一番上までスクロールすると、このジョブは本番環境にデプロイされていますメッセージが表示されます。 GitLabは、ジョブの環境セクションが原因でデプロイが行われたことを認識しています。 本番リンクをクリックして、本番環境に移動します。

すべての本番環境の展開の概要がわかります。 これまでのところ、展開は1つだけでした。 展開ごとに、右端に再展開ボタンがあります。 再デプロイは、その特定のパイプラインのデプロイジョブを繰り返します。

再デプロイメントが意図したとおりに機能するかどうかは、パイプラインの構成によって異なります。これは、同じ状況でデプロイジョブを繰り返す以上のことは行わないためです。 コミットSHAをタグとして使用してDockerイメージをデプロイするように構成したため、パイプラインで再デプロイが機能します。

注:GitLabコンテナーレジストリに有効期限ポリシーがある場合があります。 有効期限ポリシーは、コンテナレジストリから古いイメージとタグを定期的に削除します。 結果として、有効期限ポリシーより古いデプロイメントは再デプロイに失敗します。これは、このコミットのDockerイメージがレジストリから削除されるためです。 有効期限ポリシーは、設定> CI/CD>コンテナレジストリタグの有効期限ポリシーで管理できます。 有効期限は通常、90日などの高い値に設定されます。 ただし、有効期限ポリシーのためにレジストリから削除されたイメージをデプロイしようとした場合は、その特定のパイプラインのpublishジョブを再実行することで問題を解決できます。 、指定されたコミットのイメージを再作成してレジストリにプッシュします。

次に、展開の表示ボタンをクリックします。これにより、 http://your_server_IP ブラウザで個人用ウェブサイトの見出しが表示されます。

最後に、サーバーにデプロイされたコンテナーを確認します。 すでに切断している場合は、ターミナルにアクセスして再度ログインしてください(sammydeployerの両方のユーザーで機能します)。

  1. ssh sammy@your_server_IP

次に、実行中のコンテナを一覧表示します。

  1. docker container ls

どれがリストされます my-app 容器:

Output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5b64df4b37f8 registry.your_gitlab.com/your_gitlab_user/your_project/master:your_commit_sha "nginx -g 'daemon of…" 4 hours ago Up 4 hours 0.0.0.0:80->80/tcp my-app

Dockerコンテナーの管理の詳細については、 Ubuntu18.04にDockerをインストールして使用する方法ガイドをお読みください。

これで、展開が検証されました。 次のステップでは、デプロイメントをロールバックするプロセスを実行します。

ステップ8—展開のロールバック

次に、Webページを更新します。これにより、新しいデプロイメントが作成され、GitLab環境を使用して以前のデプロイメントが再デプロイされます。 これは、デプロイメントに欠陥がある場合のデプロイメントロールバックのユースケースをカバーしています。

に少し変更を加えることから始めます index.html ファイル:

  1. GitLabで、プロジェクトの概要に移動し、 index.html ファイル。
  2. 編集ボタンをクリックしてオンラインエディタを開きます。
  3. ファイルの内容を次のように変更します。
index.html
<html>
<body>
<h1>My Enhanced Personal Website</h1>
</body>
</html>

ページの下部にある[変更をコミット]をクリックして、変更を保存します。

変更を展開するために、新しいパイプラインが作成されます。 GitLabで、 CI / CD>Pipelinesに移動します。 パイプラインが完了したら、開くことができます http://your_server_IP 更新されたWebページのブラウザで、 My PersonalWebsiteの代わりにMyEnhanced PersonalWebsiteが表示されるようになりました。

操作>環境>本番に移動すると、新しく作成されたデプロイメントが表示されます。 次に、最初の古いデプロイメントのre-deployボタンをクリックします。

ロールバックボタンをクリックしてポップアップを確認します。

その古いパイプラインのデプロイジョブが再開され、ジョブの概要ページにリダイレクトされます。 ジョブが終了するのを待ってから開きます http://your_server_IP ブラウザで、最初の見出し個人用Webサイトが再び表示されます。

このチュートリアルを通じて達成したことを要約してみましょう。

結論

このチュートリアルでは、GitLab CI/CDを使用して継続的デプロイパイプラインを構成しました。 HTMLファイルとDockerfileで構成される小さなWebプロジェクトを作成しました。 次に、 .gitlab-ci.yml パイプライン構成:

  1. Dockerイメージをビルドします。
  2. Dockerイメージをコンテナーレジストリにプッシュします。
  3. サーバーにログインし、最新のイメージをプルして、現在のコンテナーを停止し、新しいコンテナーを開始します。

これで、GitLabは、リポジトリにプッシュするたびにWebページをサーバーにデプロイします。

さらに、GitLabとサーバーでのデプロイを確認しました。 また、2番目のデプロイメントを作成し、GitLab環境を使用して最初のデプロイメントにロールバックしました。これは、欠陥のあるデプロイメントに対処する方法を示しています。

この時点で、展開チェーン全体が自動化されています。 コードの変更を世界中や顧客とより頻繁に共有できるようになりました。 その結果、フィードバックの収集とコード変更の公開に必要な時間が短縮されるため、開発サイクルが短くなる可能性があります。

次のステップとして、ドメイン名でサービスにアクセスできるようにし、HTTPSとの通信を保護することができます。DockerコンテナのリバースプロキシとしてTraefikを使用する方法は適切なフォローアップです。