こんにちは。 エキサイト株式会社の三浦です。
アプリケーションのデプロイ方法は、エンジニアなら誰もが頭を悩ませるものでしょう。 コマンドライン、AWS CodePipeline、Jenkinsなど、様々な方法が考えられます。
今回は、ECSへのデプロイ方法としてGithub Actionsを選択したときの方法と注意点について説明していきます。
Github Actions
Github Actionsは、Github上で任意の処理を実行できる機能です。 公式には以下のように説明されています。
Automate, customize, and execute your software development workflows right in your repository with GitHub Actions. You can discover, create, and share actions to perform any job you'd like, including CI/CD, and combine actions in a completely customized workflow.
手動実行はもちろん、指定時間に実行したり、ブランチやプルリクエストに何かしらのアクションがあったタイミングで自動実行させることもできます。 例えば
などが可能です。
今回やりたいのは、「手動実行」でECSにデプロイする方法となります。
ECSへのデプロイ
Github Actionsは、 .github/workflows
ディレクトリ配下に実行処理を書いたYAMLファイルを置くことで設定することができます。
Github Actionsの実行単位は workflow
と呼ばれ、このディレクトリ配下に置かれる1ファイルごとに1workflowが設定されることになります。
ですが、ファイル作成前にまずは下準備をします。
AWS環境
今回はECSへのデプロイということで、関連する以下のようなAWSの環境を用意しておく必要があります。
- ECR
- ECS
- コード上からAWSへアクセスするためのIAMユーザ
Secretsの設定
AWSへのアクセス用のキーやSlack通知用のWebhookなどは、セキュリティ性の高いものであるため、Githubのバージョン管理に含めるべきではありません。 Github Actionsでは、Githubの「Setting -> Secrets」にて、そういった文字列を外部に見られないように保存することができます。
保存した文字列は、Github Actions実行時に ${{ secrets.保存したキー }}
の形式で参照することができます。
今回は、
を作成します。
なおSlack通知はデプロイに必須ではありませんが、これがあるとデプロイの運用が容易になるため今回は含めています。
Task Definition
ECSに使用するTask Definition用のJSONファイルも用意しておく必要があります。 イメージ名は後から上書きするので適当で大丈夫ですが、それ以外については適切なファイルを作っておきます。
設定ファイル
ここまで準備できたら、ようやくGithub Actionsの設定ファイルを作成します。
name: Deploy # 同じ文字列がconcurrencyに指定されているworkflowは、二重で実行できなくなります concurrency: deploy # 手動実行をさせるため、workflow_dispatchを指定してください on: workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest env: ECR_REPOSITORY: sample-ecr CLUSTER_NAME: sample-cluster SERVICE_NAME: sample-service TASK_DEFINITION: task-definition.json steps: - name: Checkout uses: actions/checkout@v2 # AWS環境へデプロイするため、認証を行います - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 # Dockerイメージをビルドし、ECRにpushします。また、outputでイメージ名を出力します # イメージのタグ名にはコミットSHAを使用します - name: Build, tag, and push image to Amazon ECR id: build-image env: IMAGE_NAME: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }} IMAGE_TAG: ${{ github.sha }} run: | docker build -t $IMAGE_NAME:$IMAGE_TAG -t $IMAGE_NAME:latest . docker push $IMAGE_NAME:$IMAGE_TAG docker push $IMAGE_NAME:latest echo "::set-output name=image::$IMAGE_NAME:latest" # 出力されたイメージ名で、 あらかじめ作成しておいたTask DefinitionのJSONファイルのイメージ名を上書きします - name: Fill the Amazon ECS task definition with image ID id: task-def uses: aws-actions/amazon-ecs-render-task-definition@v1 with: task-definition: ${{ env.TASK_DEFINITION }} container-name: sample image: ${{ steps.build-image.outputs.image }} # 作成したTaskDefinitionを元にECSへのデプロイを行います - name: Deploy Amazon ECS task definition uses: aws-actions/amazon-ecs-deploy-task-definition@v1 with: task-definition: ${{ steps.task-def.outputs.task-definition }} cluster: ${{ env.CLUSTER_NAME }} service: ${{ env.SERVICE_NAME }} wait-for-service-stability: true # Slackへ通知します - name: Slack Notification if: always() uses: rtCamp/action-slack-notify@v2 env: SLACK_CHANNEL: '#sample' SLACK_COLOR: ${{ (job.status == 'success' && 'good') || 'danger' }} SLACK_TITLE: "[${{ github.repository }}] にデプロイしました" SLACK_MESSAGE: "デプロイ結果:${{ job.status }}" SLACK_USERNAME: github actions SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} MSG_MINIMAL: ref,actions url
これで、準備は完了です。
あとは、Githubの「Actions」から手動で実行すればデプロイが可能です。
注意点
Github Actionsで手動実行する際、いくつか注意点があります。
ブランチしか選択できない(解決済み!)
かつては手動実行する際に選択できるのはブランチのみでしたが、最近になってタグを選択できるようになりました! 特にデプロイではタグによって制御している場合も多いと思うので、これは非常に嬉しいアップデートです!
デフォルトブランチにマージされないと実行できない
手動実行する場合は、デフォルトブランチにYAMLファイルがマージされていないと項目が出てきません。 最初は詰まりやすいところだと思いますので、注意しましょう。
デプロイをしたブランチ / タグがどれだか分かりづらい
ブランチやプルリクエストのアクションで自動実行されるものはGithub Actionsの一覧画面で実行元のブランチやタグが表示されていますが、手動実行のものは表示されないようです。 少し手間ですが、実行ログの「Checkout -> Checking out the ref」から確認できます。
uses
で指定しているライブラリではできないことがある
例えば aws-actions/amazon-ecs-deploy-task-definition@v1
では、2021/12/13現在、ECSでのデプロイ時に platform-version
の指定ができないようです。
指定したい場合は、自分でAWS CLIを使うようにするなど、方法を変えると良いでしょう。
最後に
Github Actionsは、
- Githubをバージョン管理に使用している場合、リポジトリと密接につながっているため、エンジニアが見る場所がバラけづらい
- 完全に独立した環境のため、共用デプロイサーバのように同時実行時のCPUやメモリの心配をする必要がない
- Github Actions用の様々なライブラリが存在するため、やりたいことを簡単に設定できる
などの利点があります。 みなさんもぜひ使ってみてはいかがでしょうか?