GithubActionsを利用して、新しいコンテナイメージをビルドして Amazon ECR にプッシュ、Amazon ECS にデプロイする手順をまとめました。
所々で学習中の Rails7 + MySQL の名前を使っています。適宜ご自身のケースに置き換えてください。
※やってみた的な要素が強いですので、初歩的な部分も含めて記載しています。おかしい部分がありましたらご指摘いただけるとありがたいです。
概要
大まかなフローと概要は以下のような感じです。
次のステップからさっそく手を動かしていきます。
IAMユーザー
ECRリポジトリにプッシュするため、リポジトリ更新権限を持つユーザーが必要です。
なければ以下の手順で作成します。
許可のオプション:ポリシーを直接アタッチ
許可ポリシー:AmazonElasticContainerRegistryPublicFullAccess
※更新権限があればよいので PowerUser でもOK
アクセスキー作成
Github Actions 内でAWS接続を行うため、認証情報を作成する
ユーザーの詳細 → セキュリティ認証情報
ユースケース:いったんその他を選択
タグ:分かればなんでもOK
作成されたアクセスキー・シークレットアクセスキーをコピーして保存
※後述のGithub Actionsでの作業時に使用します
ECRリポジトリ作成
https://ap-northeast-1.console.aws.amazon.com/ecr/repositories?region=ap-northeast-1
可視性:プライベート
リポジトリ名:任意の名前(Githubのリポジトリ名が無難?
タグのイミュータビリティ:有効
※同一タグ名で上書きされなくなる ※latest運用しない
クラスター作成
※事前にVPCとサブネットを設定しておく
クラスター名:ecs-rails7-mysql-cluster
VPC:事前に作成しておいたもの
サブネット:事前に作成しておいたもの
インフラストラクチャ:Fargete
※以下のようなエラーが発生してクラスター作成が失敗する場合
すこし時間をおいてから再度実行
Resource handler returned message: "Error occurred during operation 'CreateCluster SDK error: Service Unavailable. Please try again later
タスク定義の作成
ステップ1
タスク定義ファミリー:識別できればなんでもOK
コンテナ名:Githubリポジトリ名など
イメージURI:ECRにあるイメージを指定する必要がるので、事前になにかイメージ(latestなど)をアップしておく
イメージプッシュについての記事:https://qiita.com/sakuchi/items/90886663f7adf3941472
ステップ2
アプリケーション環境:Fargate
タスクサイズ:CPU- .5vCPU メモリ1GB
※学習用なので最小スペックを選択。
デフォルトは最小値になっていないので必ず変更する
ログ収集の使用:学習用なので使用しない
task-definition.json作成
Githubのルートに配置。
後述の Actions で作業する際に使用します。
ビルドしたイメージを動的にタスク定義に紐づけるため、imageに環境変数を指定します。
"image": "${{ env.ECR_REGISTRY }}/rails7-mysql:${{ env.IMAGE_TAG }}",
サービスの作成
超重要:常時このコンテナ(タスク)を起動しておくための設定。
サービスは常に指定した数のタスクを実行することを保証し、タスクが異常終了した場合には自動的に新しいタスクが起動される。つまりコンソール上でタスクを停止しても、タスク数が0になっていない限りサービスによって自動で起動される。料金に大きく影響するので注意。
環境
コンピューティング設定:起動タイプ
起動タイプ:Fargate
デプロイ設定
アプリケーションタイプ:サービス
ファミリー:前述で作成したタスク定義
サービス名:なんでもOK
サービスタイプ:レプリカ
必要なタスク:1
※ここで設定したタスク数にAWSが自動で調整する。
デプロイオプション
デフォルトのまま
ネットワーキング
VPC:今回作成したもの
サブネット::今回作成したもの
セキュリティグループ:既存のセキュリティグループを使用
パブリックIP:オン
ロードバランシング:なし
Auto Scaling:使用しない
タグ:デフォルト
Github Actions でビルド・プッシュ設定
Github Actions でビルド・プッシュ設定
Github側でIAMユーザーのアクセスキーとシークレットアクセスキーを設定
※後述のワークフロー内で使用する
ワークフローファイルの作成
今回は mainブランチに対して行います
ymlの記述を以下に変更
name: Deploy to Amazon ECS
on:
push:
branches: [main]
env:
AWS_REGION: ap-northeast-1 # set this to your preferred AWS region, e.g. us-west-1
ECR_REPOSITORY: rails7-mysql # set this to your Amazon ECR repository name
ECS_SERVICE: svc-rails7-mysql # set this to your Amazon ECS service name
ECS_CLUSTER: ecs-rails7-mysql-cluster # set this to your Amazon ECS cluster name
ECS_TASK_DEFINITION: task-definition.json # set this to the path to your Amazon ECS task definition
# file, e.g. .aws/task-definition.json
CONTAINER_NAME: rails7-mysql # set this to the name of the container in the
# containerDefinitions section of your task definition
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
steps:
# ワークフローファイル内で利用できるように、リポジトリをチェックアウト
- name: Checkout repository
uses: actions/checkout@v3
# 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: ${{ env.AWS_REGION }}
# ECR にログイン
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
# リポジトリ内の Dockerfile を使用して、イメージのビルド、タグ付けをして ECR にプッシュ
- name: Build, tag, and push docker image to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: rails7-mysql
#IMAGE_TAG: latest
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
#イメージのURLを保持
echo "IMAGE_URL=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_ENV
- name: Use IMAGE_URL
run: |
echo ${{ env.IMAGE_URL }}
# ECSタスク定義のイメージID を新しくビルドしたイメージに更新。これにより新しいイメージがデプロイされる。
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.ECS_TASK_DEFINITION }}
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ env.IMAGE_URL }}
# 新しいタスク定義でデプロイ。指定したタスク定義とクラスタ、サービスを使用して、既存のタスクを更新。
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
環境変数について
AWS_REGION: ECR,ECSのリージョン(例:ap-northeast-1
ECR_REPOSITORY: ECRリポジトリ名 (例:rails7-mysql
ECS_SERVICE: ECSサービス名 (例:svc-rails7-mysql
ECS_CLUSTER: ECSクラスター名 (例:ecs-rails7-mysql-cluster
ECS_TASK_DEFINITION: task-definition.json (例:task-definition.json
CONTAINER_NAME: タスク定義で指定したコンテナ名 (例:rails7-mysql
※注意点など
構築の流れは一通り以上です。
これで mainブランチにpushが発生するとワークフローファイルをもとにビルド・プッシュ・デプロイが行われるようになります。
学習用の場合、最後に必ずサービスの「必要なタスク」を 0 に設定するか、サービス自体を削除するようにしてください。タスクが起動している間は料金が発生しますのでご注意ください。
サービスが存在していてもタスクが起動していなければ料金は発生しません。