アプリケーションに CI/CD を設定

このページでは、 Docker コンテナを使う GitHub Actions CI/CD パイプラインのセットアップ手順を説明します。新しいパイプラインを設定する前に、 Ben のブログ にある CI/CD ベストプラクティスをご覧になるのを推奨します。

このガイドには、以下の方法の手順を含みます:

  1. サンプル Docker プロジェクトを例に GitHub Actions を設定する

  2. GitHub Actions ワークフローをセットアップする

  3. pull リクエストを減らすようワークフローを最適化し、採取的に合計構築時間を減らす

  4. 特定のバージョンのみ Docker Hub に送信する

Docker プロジェクトのセットアップ

それでは始めましょう。このガイドでは例としてシンプルな Docker プロジェクトを使います。 SimpleWhaleDemo リポジトリは Nginx alpine イメージを含みます。このリポジトリを複製するか、自分の Docker プロジェクトを使います。

SimpleWhaleDemo

始める前に、作成するあらゆるワークフローが Docker Hub にアクセスできるようにします。そのためには:

  1. 自分の Docker ID をシークレットとして GitHub に追加します。自分の GitHub リポジトリに移動し、 Settings > Secrets > New secret をクリックします。

  2. DOCKER_HUB_USERNAME という名前で新しいシークレットを作成し、値として自分の Docker ID を入れます。

  3. 新しい パーソナル アクセス トークン(Personal Access Token) (PAT)を作成します。 Docker Hub Settings に移動し、 New Access Token をクリックします。

  4. このトークンを simplewhaleci と呼びましょう。

    New access token
  5. それから GitHub secrets UI で、この パーソナル アクセス トークン(Personal Access Token) (PAT)を2番目のシークレットとして DOCKER_HUB_ACCESS_TOKEN という名前の値に追加します。

    New access token

GitHub Actions ワークフローのセットアップ

前のセクションでは、GitHub のあらゆるワークフローが Docker Hub にアクセスできるようにするため、 PAT を作成して追加しました。次は、 GitHub Actions ワークフローをセットアップし、イメージの構築と Hub への保存をします。これを達成するには、2つの Docker Actions を以下の YAML ファイルで作成します。

  1. 1つめのアクションは、 GitHub リポジトリ内に保存したシークレットを使い、 Docker Hub にログインできるようにします。

  2. 2つめのアクションは、構築と送信をします。

この例では、 push(送信)フラグを true に設定し、送信もします。それから、常に 最新(latest) バージョンに移動するよう指定するタグを追加します。最後に、何が送信されたか見るために、イメージのダイジェスト値を表示します。

ワークフローをセットアップするには:

  1. 自分の GitHub リポジトリに移動し、 Actions > New workflow をクリックします。

  2. set up a workflow yourself をクリックし、以下の内容を追加します。

まず、このワークフローに名前を付けます。

name: CI to Docker Hub

それから、このワークフローをいつ実行するかを選びます。私たちの例では、プロジェクトの master ブランチに対する全ての push に対して実行するようにします。

on:
  push:
    branches: [ master ]

注釈

ブランチ名は mainmaster でしょう。自分のリポジトリにあるブランチ名を確認し、設定を適切に書き換えてください。

次は Actions 内で実際に何が起こるか(何の仕事をするか)を指定する必要があるため、build を追加し、利用可能な最新の Ubuntu インスタンスで実行するのを選択しました。

jobs:

  build:
    runs-on: ubuntu-latest

次は、必要な steps を追加できます。1つめは、 $GITHUB_WORKSPACE 以下のリポジトリを調べ、ワークフローがアクセスできるようにします。2つめは、PAT とユーザ名を使い Docker Hub へログインします。3つめは Builder で、このアクションが簡単な Buildx アクションを通して BuildKit を使えるようにセットアップもします。

steps:

  - name: Check Out Repo
    uses: actions/checkout@v2

  - name: Login to Docker Hub
    uses: docker/login-action@v1
    with:
      username: ${{ secrets.DOCKER_HUB_USERNAME }}
      password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

  - name: Set up Docker Buildx
    id: buildx
    uses: docker/setup-buildx-action@v1

  - name: Build and push
    id: docker_build
    uses: docker/build-push-action@v2
    with:
      context: ./
      file: ./Dockerfile
      push: true
      tags: ${{ secrets.DOCKER_HUB_USERNAME }}/simplewhale:latest

  - name: Image digest
    run: echo ${{ steps.docker_build.outputs.digest }}

これで、ワークフローを初めて実行すると、調整した Dockerfile で CI を実行し、新しいイメージの変更が push されているのをかくにんします。

Docker Hub への CI

ワークフローの最適化

次は、構築キャッシュを通して GitHub Actions ワークフローをどのようにして最適化できるか見ていきます。これには2つの主な利点があります:

  1. 構築キャッシュはイメージ全てを再ダウンロードする必要がないため、構築回数を減らします。さらに、

  2. Docker Hub から取得する回数も減らします。これを実現するには GitHub cache を使えるようにする必要があります。

構築キャッシュを使うよう builder をセットアップしましょう。まず、builder 用のキャッシュをセットアップする必要があります。この例では、 GitHub キャッシュを使うために保存するパスとキーを追加します。

- name: Cache Docker layers
  uses: actions/cache@v2
  with:
    path: /tmp/.buildx-cache
    key: ${{ runner.os }}-buildx-${{ github.sha }}
    restore-keys: |
      ${{ runner.os }}-buildx-

そして遂に、 builder と 構築キャッシュ断片(build cache snippet) を Actions ファイルの先頭に追加したら、build と push ステップのために追加属性を加える必要があります。こちらを含みます。

- name: Login to Docker Hub
  uses: docker/login-action@v1
  with:
    username: ${{ secrets.DOCKER_HUB_USERNAME }}
    password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Build and push
  id: docker_build
  uses: docker/build-push-action@v2
  with:
    context: ./
    file: ./Dockerfile
    builder: ${{ steps.buildx.outputs.name }}
    push: true
    tags: ${{ secrets.DOCKER_HUB_USERNAME }}/simplewhale:latest
    cache-from: type=local,src=/tmp/.buildx-cache
    cache-to: type=local,dest=/tmp/.buildx-cache
- name: Image digest
  run: echo ${{ steps.docker_build.outputs.digest }}

これで、再びワークフローを実行し、構築キャッシュがワークフローで使われるのを確認します。

Docker Hub にタグ付けされたバージョンを送信

これまで学んだのは、 Docker プロジェクトに対して GitHub Actions ワークフローをセットアップする方法や、構築キャッシュを builder で使うようにセットアップしてワークフローを最適化する方法でした。それでは更に改良する方法を見ていきましょう。master に対するすべてのコミットではなく、タグ付けされたバージョンのみ追加できるようにします。つまり、コミットするたびに毎回 Docker Hub に送信するのではなく、指定したバージョンのみ送信できます。

この手法は、ローカルのレジストリに対してコミットし、これを夜間テストで使うために考えられます。これをするには、Docker Hub にタグ付けされたバージョンがリリースされた時、常に指定された最新版かどうかを確認します。

2つのステップで、この改良をします:

  1. 指定したタグでのコミットのみ Docker Hub へ送信するよう、GitHub ワークフローを変更

  2. GitHub レジストリ内への最新のコミットをイメージとして保存するよう、GitHub Actions ファイルをセットアップ

まず、既存の GitHub ワークフローを変更し、特定のタグがある場合のみ Hub に送信するようにします。例:

on:
  push:
    tags:
      - "v*.*.*"

コミットに V.n.n.n. のタグがある場合のみをトリガとして、メイン CI が動作するのを確認します。そのためには、たとえば以下のコマンドを実行します。

$ git tag -a v1.0.2
$ git push origin v1.0.2

次は、 GitHub に移動し Actions を確認します。

タグ付けされたバージョンを送信

次は、2つめの GitHub Action ファイルを編集し、GitHub レジストリ内に最新のコミットのみイメージとして保存するようにします。これをするには、次のように設定するでしょう。

  1. 夜間テストや再帰テストの実行。または、

  2. 作業中イメージを同僚に共有

先ほどの GItHub Action を複製し、すべての push する前の手順に戻しましょう。つまり、2つのワークフローを用意します。1つは先ほどのもので、新しいものは今から作ります。次に、GitHub コンテナレジストリにログインするため、Docker Hub ログインを書き換えます。

if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
  registry: ghcr.io
  username: ${{ github.actor }}
  password: ${{ secrets.GITHUB_TOKEN }}

GitHub Container Registry へ認証するには、最高のセキュリティと経験から GITHUB_TOKEN を使います。

リポジトリ内のコンテナ設定に GitHub Actions の読み書き権限の管理 が必要な場合があります。

適切な範囲パーソナルアクセストークン(PAT) を使う場合もあります。イメージのタグ付け変更を思い出してください。以下の例は「latest」のみ唯一のタグとして保持します。しかしながら、任意のものへと書き換えできます。

tags: ghcr.io/${{ github.repository_owner }}/simplewhale:latest
タグ付けされたイメージの更新

これで、2つの異なるフローができました:1つは変更を master に送り、もう1つは pull request のためです。次に、Docker Hub ではなく GitHub に Pull Request を送信するよう、以前のものを買い換える必要があります。

次のステップ

この章では、既存の DOcker プロジェクトに GitHub Actions ワークフローをセットアップする方法、構築回数と pull request 数を減らすようワークフローの最適化、そして最後に、特定のバージョンのみ Docker Hub に送信する方法を説明しました。また、 latest タグに対して夜間テストをしたり、各 PR のテスト、タグを使ってより洗練された何かを実行したりイメージ内のタグに Git タグを同じものも使用するようにセットアップできます。

アプリケーションのデプロイも検討できます。詳細な手順は、こちらをご覧ください:

アプリのデプロイ

フィードバック

フィードバックを通し、このトピックの改善を支援ください。考えがあれば、 Docker Docs GitHub リポジトリに issue を作成して教えてください。あるいは、更新の提案のために RP を作成 してください。

参考

Configure CI/CD for your application

https://docs.docker.com/language/nodejs/configure-ci-cd/