序章

コンテナ化は、クラウド環境でアプリケーションをパッケージ化およびデプロイするための最も受け入れられている方法に急速になりつつあります。 それが提供する標準化は、そのリソース効率(完全な仮想マシンと比較した場合)および柔軟性とともに、最新のDevOpsマインドセットの優れたイネーブラーになります。 アプリケーションとマイクロサービスが完全にコンテナー化されると、多くの興味深いクラウドネイティブのデプロイ、オーケストレーション、および監視戦略が可能になります。

Docker コンテナーは、今日最も一般的なコンテナータイプです。 Docker Hub のようなパブリックDockerイメージリポジトリには、docker pullで今日使用できるコンテナ化されたオープンソースソフトウェアイメージがたくさんありますが、プライベートコードの場合は、ビルドするためにサービスを支払う必要があります。画像を保存するか、独自のソフトウェアを実行して保存します。

GitLab Community Editionは、Gitリポジトリホスティング、プロジェクトトラッキング、CI / CDサービス、Dockerイメージレジストリなどの機能を提供するセルフホストソフトウェアスイートです。 このチュートリアルでは、GitLabの継続的インテグレーションサービスを使用して、サンプルのNode.jsアプリからDockerイメージを構築します。 これらのイメージはテストされ、独自のプライベートDockerレジストリにアップロードされます。

前提条件

始める前に、継続的インテグレーションタスクを実行するために安全なGitLabサーバーGitLabCIランナーをセットアップする必要があります。 以下のセクションでは、リンクと詳細を提供します。

SSLで保護されたGitLabサーバー

ソースコードを保存し、CI / CDタスクを実行し、Dockerレジストリをホストするには、Ubuntu16.04サーバーにGitLabインスタンスをインストールする必要があります。 GitLabは現在、少なくとも2つのCPUコアと4GBのRAMを備えたサーバーを推奨しています。 さらに、Let’sEncryptのSSL証明書を使用してサーバーを保護します。 そのためには、サーバーを指すドメイン名が必要です。

次のチュートリアルを使用して、これらの前提条件を完了することができます。

GitLabCIランナー

Ubuntu16.04でGitLabCIと継続的インテグレーションパイプラインを設定する方法では、GitLabのCIサービスの概要を説明し、ジョブを処理するためのCIランナーを設定する方法を示します。 このチュートリアルで作成したデモアプリとランナーインフラストラクチャの上に構築します。

ステップ1—特権GitLabCIランナーのセットアップ

前提条件のGitLab継続的インテグレーションチュートリアルでは、sudo gitlab-runner registerとそのインタラクティブな構成プロセスを使用してGitLabランナーをセットアップしました。 このランナーは、分離されたDockerコンテナー内でソフトウェアのビルドとテストを実行できます。

ただし、Dockerイメージをビルドするには、ランナーがDockerサービス自体に完全にアクセスできる必要があります。 これを構成するための推奨される方法は、Dockerの公式docker-in-dockerイメージを使用してジョブを実行することです。 これには、ランナーに特別なprivileged実行モードを付与する必要があるため、このモードを有効にして2番目のランナーを作成します。

注:ランナーに特権モードを付与すると、基本的に、コンテナーを使用することによるセキュリティ上の利点がすべて無効になります。 残念ながら、Docker対応のランナーを有効にする他の方法にも同様のセキュリティ上の影響があります。 さまざまなランナーオプションの詳細と、状況に最適なものについては、 DockerBuildに関する公式のGitLabドキュメントをご覧ください。

特権ランナーの使用にはセキュリティ上の影響があるため、hello_hapiプロジェクトでDockerジョブのみを受け入れるプロジェクト固有のランナーを作成します(GitLab管理者は、このランナーを他のプロジェクトにいつでも手動で追加できます。後で)。 hello_hapiプロジェクトページで、左側のメニューの下部にある設定をクリックし、サブメニューの CI /CDをクリックします。

GitLab project settings menu

次に、ランナー設定セクションの横にある展開ボタンをクリックします。

GitLab "Runners settings" expand button

登録トークンなど、特定のランナーの設定に関する情報があります。 このトークンに注意してください。 これを使用して新しいランナーを登録すると、ランナーはこのプロジェクトにのみロックされます。

GitLab project-specific runners options

このページを表示しているときに、共有ランナーを無効にするボタンをクリックします。 Dockerジョブが常に特権ランナーで実行されるようにする必要があります。 非特権の共有ランナーが利用可能な場合、GitLabはそのランナーを使用することを選択する可能性があり、その結果、ビルドエラーが発生します。

現在のCIランナーが存在するサーバーにログインします。 ランナーを使用してマシンをセットアップしていない場合は、先に進む前に、前提条件のチュートリアルのGitLabCIランナーサービスのインストールセクションに戻って完了してください。

次に、次のコマンドを実行して、特権プロジェクト固有のランナーを設定します。

  1. sudo gitlab-runner register -n \
  2. --url https://gitlab.example.com/ \
  3. --registration-token your-token \
  4. --executor docker \
  5. --description "docker-builder" \
  6. --docker-image "docker:latest" \
  7. --docker-privileged
Output
Registering runner... succeeded runner=61SR6BwV Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

必ず自分の情報に置き換えてください。 プロンプトでは--docker-privilegedモードを指定できないため、インタラクティブプロンプトを使用する代わりに、コマンドラインですべてのランナーオプションを設定します。

これで、ランナーがセットアップされ、登録され、実行されます。 確認するには、ブラウザに戻ります。 メインのGitLabメニューバーのレンチアイコンをクリックしてから、左側のメニューのRunnersをクリックします。 ランナーが一覧表示されます:

GitLab runner listing

Dockerイメージを構築できるランナーができたので、イメージをプッシュするためのプライベートDockerレジストリを設定しましょう。

ステップ2—GitLabのDockerレジストリを設定する

独自のDockerレジストリを設定すると、独自のプライベートサーバーからイメージをプッシュおよびプルできるため、セキュリティが強化され、ワークフローが外部サービスに依存することが少なくなります。

GitLabは、いくつかの構成を更新するだけでプライベートDockerレジストリをセットアップします。 まず、レジストリが存在するURLを設定します。 次に、(オプションで)S3互換のオブジェクトストレージサービスを使用してデータを保存するようにレジストリを構成します。

GitLabサーバーにSSHで接続し、GitLab構成ファイルを開きます。

  1. sudo nano /etc/gitlab/gitlab.rb

コンテナレジストリ設定セクションまで下にスクロールします。 registry_external_url行のコメントを解除し、ポート番号が5555のGitLabホスト名に設定します。

/etc/gitlab/gitlab.rb
registry_external_url 'https://gitlab.example.com:5555'

次に、次の2行を追加して、Let’sEncrypt証明書の場所をレジストリに通知します。

/etc/gitlab/gitlab.rb
registry_nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.example.com/fullchain.pem"
registry_nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.example.com/privkey.pem"

ファイルを保存して閉じてから、GitLabを再構成します。

  1. sudo gitlab-ctl reconfigure
Output
. . . gitlab Reconfigured!

レジストリポートへのトラフィックを許可するようにファイアウォールを更新します。

  1. sudo ufw allow 5555

次に、Dockerがインストールされている別のマシンに切り替えて、プライベートDockerレジストリにログインします。 ローカル開発コンピューターにDockerがない場合は、Dockerが既にインストールされているため、GitLabCIジョブを実行するように設定されているサーバーを使用できます。

  1. docker login gitlab.example.com:5555

ユーザー名とパスワードの入力を求められます。 GitLabクレデンシャルを使用してログインします。

Output
Login Succeeded

成功! レジストリが設定され、機能しています。 現在、GitLabサーバーのローカルファイルシステムにファイルを保存します。 代わりにオブジェクトストレージサービスを使用する場合は、このセクションに進んでください。 そうでない場合は、ステップ3にスキップします。

レジストリのオブジェクトストレージバックエンドを設定するには、オブジェクトストレージサービスに関する次の情報を知っている必要があります。

  • アクセスキー
  • シークレットキー
  • たとえば、AmazonS3を使用している場合はRegion us-east-1)、S3互換サービスを使用している場合は Region Endpoint https://nyc.digitaloceanspaces.com
  • バケット名

DigitalOcean Spacesを使用している場合は、 DigitalOceanSpaceとAPIキーの作成方法を読んで、新しいSpaceを設定する方法と上記の情報を取得する方法を確認できます。

オブジェクトストレージ情報を入手したら、GitLab構成ファイルを開きます。

  1. sudo nano /etc/gitlab/gitlab.rb

もう一度、コンテナレジストリセクションまでスクロールダウンします。 registry['storage']ブロックを探し、コメントを外して、次のように更新します。ここでも、必要に応じて独自の情報に置き換えてください。

/etc/gitlab/gitlab.rb
registry['storage'] = {
  's3' => {
    'accesskey' => 'your-key',
    'secretkey' => 'your-secret',
    'bucket' => 'your-bucket-name',
    'region' => 'nyc3',
    'regionendpoint' => 'https://nyc3.digitaloceanspaces.com'
  }
}

Amazon S3を使用している場合は、regionのみが必要であり、regionendpointは必要ありません。 SpacesなどのS3互換サービスを使用している場合は、regionendpointが必要です。 この場合、regionは実際には何も構成せず、入力する値は重要ではありませんが、空白ではなく存在する必要があります。

ファイルを保存して閉じます。

注:現在、オブジェクトストレージバケットが空の場合、30秒後にレジストリがシャットダウンするというバグがあります。 これを回避するには、次の手順を実行する前にファイルをバケットに入れます。 レジストリが独自のオブジェクトを追加した後、後で削除できます。

DigitalOcean Spacesを使用している場合は、コントロールパネルインターフェイスを使用してドラッグアンドドロップでファイルをアップロードできます。

GitLabをもう一度再構成します。

  1. sudo gitlab-ctl reconfigure

他のDockerマシンで、レジストリに再度ログインして、すべてが正常であることを確認します。

  1. docker login gitlab.example.com:5555

Login Succeededメッセージが表示されます。

Dockerレジストリーがセットアップされたので、アプリケーションのCI構成を更新してアプリをビルドおよびテストし、Dockerイメージをプライベートレジストリーにプッシュします。

ステップ3—gitlab-ci.yamlを更新してDockerイメージを構築する

注: GitLab CI に関する前提条件の記事を完了していない場合は、サンプルリポジトリをGitLabサーバーにコピーする必要があります。 GitHubからのサンプルリポジトリのコピーセクションに従ってください。

Dockerでアプリをビルドするには、.gitlab-ci.ymlファイルを更新する必要があります。 このファイルをGitLabで直接編集するには、プロジェクトのメインページからファイルをクリックし、編集ボタンをクリックします。 または、リポジトリをローカルマシンに複製し、ファイルを編集してから、git pushしてGitLabに戻すこともできます。 これは次のようになります。

  1. git clone [email protected]:sammy/hello_hapi.git
  2. cd hello_hapi
  3. # edit the file w/ your favorite editor
  4. git commit -am "updating ci configuration"
  5. git push

まず、ファイル内のすべてを削除してから、次の構成で貼り付けます。

.gitlab-ci.yml
image: docker:latest
services:
- docker:dind

stages:
- build
- test
- release

variables:
  TEST_IMAGE: gitlab.example.com:5555/sammy/hello_hapi:$CI_COMMIT_REF_NAME
  RELEASE_IMAGE: gitlab.example.com:5555/sammy/hello_hapi:latest

before_script:
  - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN gitlab.example.com:5555

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

test:
  stage: test
  script:
    - docker pull $TEST_IMAGE
    - docker run $TEST_IMAGE npm test

release:
  stage: release
  script:
    - docker pull $TEST_IMAGE
    - docker tag $TEST_IMAGE $RELEASE_IMAGE
    - docker push $RELEASE_IMAGE
  only:
    - master

強調表示されたURLとユーザー名を自分の情報で更新してから、GitLabの変更のコミットボタンで保存してください。 GitLabの外部でファイルを更新する場合は、変更をコミットしてgit pushをGitLabに戻します。

この新しい構成ファイルは、GitLabに最新のDockerイメージ(image: docker:latest)を使用し、それをdocker-in-dockerサービス(docker:dind)にリンクするように指示します。 次に、buildtest、およびreleaseステージを定義します。 buildステージは、リポジトリで提供されるDockerfileを使用してDockerイメージを構築し、それをDockerイメージレジストリにアップロードします。 それが成功すると、testステージは、作成したばかりのイメージをダウンロードし、その中でnpm testコマンドを実行します。 テストステージが成功すると、releaseステージがイメージをプルし、hello_hapi:latestのタグを付けて、レジストリにプッシュバックします。

ワークフローに応じて、testステージを追加したり、アプリをステージング環境または本番環境にプッシュするdeployステージを追加したりすることもできます。

構成ファイルを更新すると、新しいビルドがトリガーされるはずです。 GitLabのhello_hapiプロジェクトに戻り、コミットのCIステータスインジケーターをクリックします。

GitLab commit notification with pipeline status icon

結果のページで、ステージのいずれかをクリックして、進行状況を確認できます。

GitLab pipeline detail

GitLab pipeline stage progress

最終的には、すべてのステージで、緑色のチェックマークアイコンを表示して成功したことを示す必要があります。 左側のメニューのRegistry項目をクリックすると、ビルドされたばかりのDockerイメージを見つけることができます。

GitLab container registry image list

画像名の横にある小さな「ドキュメント」アイコンをクリックすると、適切なdocker pull ...コマンドがクリップボードにコピーされます。 次に、イメージをプルして実行できます。

  1. docker pull gitlab.example.com:5555/sammy/hello_hapi:latest
  2. docker run -it --rm -p 3000:3000 gitlab.example.com:5555/sammy/hello_hapi:latest
Output
> [email protected] start /usr/src/app > node app.js Server running at: http://56fd5df5ddd3:3000

イメージはレジストリからプルダウンされ、コンテナで開始されました。 ブラウザに切り替え、ポート3000でアプリに接続してテストします。 この場合、ローカルマシンでコンテナを実行しているため、次のURLでlocalhostを介してコンテナにアクセスできます。

http://localhost:3000/hello/test
Output
Hello, test!

成功! CTRL-Cでコンテナを停止できます。 これ以降、リポジトリのmasterブランチに新しいコードをプッシュするたびに、新しいhello_hapi:latestイメージを自動的にビルドしてテストします。

結論

このチュートリアルでは、Dockerイメージをビルドするための新しいGitLabランナーをセットアップし、それらを格納するためのプライベートDockerレジストリを作成し、Dockerコンテナー内でビルドおよびテストするためにNode.jsアプリを更新しました。

このセットアップで使用されるさまざまなコンポーネントの詳細については、 GitLab CE GitLab Container Registry 、およびDockerの公式ドキュメントを参照してください。