Perl Hackers Hub

第61回GitHub ActionsとAmazon ECSを使ったDockerアプリケーションの自動デプロイ(3)

(1)こちら⁠2)こちらから。

GitHub Actions─⁠─ ビルドとデプロイプロセスの自動化

(3)では、先ほど作成したECS環境に、GitHub Actionsを用いて自動的にアプリケーションをビルドしてデプロイするしくみを構築します。

GitHub Actionsとは、GitHubがgithub.comに統合した形で提供するCIContinuous Integration継続的インテグレーション)/CDContinuous Delivery継続的デリバリ)環境です。GitHub Actionsには、ソースコードのpullやPull Requestのアサインといった豊富な機能(アクション)が用意されています。ユーザーは、アクションと実行タイミングや実行環境などを組み合わせ、ワークフローと呼ばれるYAMLYAML Ain't Markup Languageファイルにまとめます。リポジトリの所定の位置にこのYAMLファイルを配置すると、GitHubがそのとおりにワークフローを実行してくれます。

今回はブランチモデルとして、git-flow方式に似た構成を採用します。すなわち、デプロイ用のブランチとしてmasterを使い、デプロイの前段階としての開発用ブランチにdevelブランチを使います。

cpanfile.snapshotを自動で生成しよう

cpanfile.snapshotは、carton installを実行する環境によっては異なるものが生成されます。そのため、各開発者の手もとでcpanfileとともにcpanfile.snapshotをコミットする方法で開発している場合、cpafile.snapshotが頻繁に変化してしまうことがあります。これを防ぐために、GitHub Actionsを使ってcpanfile.snapshotを集中的に生成しましょう。

ワークフローの定義

では、.github/workflows/perl.ymlにワークフローを定義しましょう。

on:
  push:
    branches:
      - devel
  pull_request:
    branches:
      - devel
jobs:
  cpan:
    runs-on: ubuntu-latest
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
    - uses: actions/checkout@v2
    - name: Generate cpanfile.snapshot
      working-directory: ./application
      run: |
        ./generate-cpanfile-snapshot.sh
    - uses: stefanzweifel/git-auto-commit-action@v3.0.0
      with:
        commit_message: Updated cpanfile.snapshot
        file_pattern: application/cpanfile.snapshot

前半のonブロックでは、ワークフローの実行条件を指定します。今回は、develブランチにpushされたときと、devel宛てのPull Requestで変更を検知したときを指定しています。

後半のjobsブロックが、実際の処理を記述する部分です。ワークフローは複数のジョブから成り立っており、ジョブはさらに複数のステップから成り立っています。個々のアクションはステップで実行されます。今回は、1つのジョブを作成しています。そのジョブの中で、まずcheckoutアクションを使ってソースコードをGitHub Actions上の仮想環境にチェックアウトしたあと、cpanfile.snapshotを生成するgeneratecpanfile-snapshot.shというシェルスクリプトを呼び出します。そして、git-auto-commit-actionアクションによって、cpanfile.snapshotが変更されていればコミットし、pushしています。

cpanfile.snapshotを生成するシェルスクリプトの作成

前述したgenerate-cpanfile-snapshot.shでは、cpanmやCartonをインストールし、carton installを実行してcpanfile.snapshotを生成しています。簡潔なコードなのでここでは割愛します。WEB+DB PRESS Vol.116のサポートサイトのサンプルコードを参照してください。

いざ生成

これで、自動的にcpanfile.snapshotを生成する準備ができました。perl.ymlgenerate-cpanfilesnapshot.shをコミットしてpushすると、ワークフローが起動してcpanfile.snapshotが生成されます。

Amazon ECSへデプロイしよう

GitHubには、ECSにアプリケーションをデプロイする公式アクションが用意されています。これにより、⁠特定のブランチにコミットがpushされたとき」といったタイミングでECSにイメージをデプロイできます。

ワークフローの定義

GitHubのテンプレートを使ってワークフローを作成しましょう。GitHubでリポジトリを開き、⁠Actions」タブの「New workflow」ボタンをクリックすると、⁠Deploy to Amazon ECS」という項目が表示されるので、これを選択します。すると、あらかじめ項目が埋められたYAMLファイルを編集する画面が現れます。

編集を行う前に、あらかじめ、次のリソースを用意しておきましょう。それぞれについて詳しくは、YAMLファイルのコメント(英語)をご覧ください。

  • アプリケーションのイメージが格納されるECRリポジトリ(URIではなく名前を記入する)
  • リポジトリのリージョン名
  • ECSクラスタ

YAMLファイルの各項目を次のように埋め、.github/workflows/aws.ymlとして保存します。

(省略)
- name: Build, tag, and push image to Amazon ECR
  id: build-image
  env:
    ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
    ECR_REPOSITORY: ECRリポジトリ
    IMAGE_TAG: ${{ github.sha }}
  run: |
    docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_T
AG ./application/
    docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
    echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPO
SITORY:$IMAGE_TAG"
- name: Fill in the new image ID in the Amazon ECS task de
finition
  id: task-def
  uses: aws-actions/amazon-ecs-render-task-definition@v1
  with:
    task-definition: task-definition.json
    container-name: app # ここではコンテナ名をappとする
    image: ${{ steps.build-image.outputs.image }}
- name: Deploy Amazon ECS task definition
  uses: aws-actions/amazon-ecs-deploy-task-definition@v1
  with:
    task-definition: ${{ steps.task-def.outputs.task-defin
ition }}
    service: サービス名
    cluster: クラスタ名
    wait-for-service-stability: true
(省略)

今回は、masterブランチにマージなどの変更が発生したときにデプロイしたいので、masterブランチへのpushかマージがあったときにワークフローを起動するよう、デフォルトのまま指定しました。

Amazon ECSタスク定義の作成

GitHub Actionsを使ってデプロイする場合、タスク定義としてtask-definition.jsonを用意する必要があります。手動で作成することもできますが、あらかじめブラウザ上のGUIGraphical User Interfaceでひな型を作成しておき、編集画面からコピーできるJSONを保存すると簡単です。

Amazon ECSのトップ画面から「タスク定義」タブを開き、⁠新しいタスク定義の作成」をクリックし、ウィザードにしたがってタスク定義を設定します。⁠起動タイプ」「FARGATE」を選択し、⁠コンテナの追加」をクリックしてコンテナ定義を1つ作成します。ここではコンテナ名やイメージを、ecs-cliコマンドを使ったときと同じに設定しておきます。こうして作成したタスク定義を「タスク定義」タブから開くと、JSONをコピーできます。JSONにはrequiresAttributesといったプロパティが自動で追加されていますが、これは不要なので削除します。そのほかにもデプロイ時に不要なパラメータを指摘されることがあるため、その場合は該当するプロパティを都度削除しましょう。

IAMユーザーのクレデンシャルの登録

イメージのpushやデプロイにはIAMIdentity and Access Managementユーザーが必要です。IAMユーザーを作成して、各種権限を割り当てましょう。ここでは割愛しますが、ECSのサービスを更新する権限と、ECRにアップロードする権限などを設定します。

そして、GitHubがこのIAMユーザーとして振る舞えるようにするために、作成したIAMユーザーのアクセスキーIDとシークレットアクセスキーをGitHubに登録します。これはYAMLファイルにではなく、GitHub Actions Secretsとして別画面から保存します。リポジトリの「Settings」「Secrets」を開くとクレデンシャルを追加できますので、アクセスキーIDはAWS_ACCESS_KEY_IDという名前で、シークレットアクセスキーはAWS_SECRET_ACCESS_KEYという名前で保存しましょう。

いざデプロイ

これで準備ができました。develブランチからのPullRequestをmasterブランチにマージすると、ECSクラスタにPerlアプリケーションが自動的にデプロイされます。

まとめ

今回は、ECSとGitHub Actionsを用いて、Dockerアプリケーションをすばやくビルド、デプロイする方法を解説しました。

さて、次回の執筆者は清水隆博さんで、テーマは「Perl歴史散策」です。お楽しみに。

WEB+DB PRESS

本誌最新号をチェック!
WEB+DB PRESS Vol.130

2022年8月24日発売
B5判/168ページ
定価1,628円
(本体1,480円+税10%)
ISBN978-4-297-13000-8

  • 特集1
    イミュータブルデータモデルで始める
    実践データモデリング

    業務の複雑さをシンプルに表現!
  • 特集2
    いまはじめるFlutter
    iOS/Android両対応アプリを開発してみよう
  • 特集3
    作って学ぶWeb3
    ブロックチェーン、スマートコントラクト、NFT

おすすめ記事

記事・ニュース一覧