😺

AWS ECSで自動デプロイを組んでみる

2022/02/20に公開

概要

GitHub にコードをプッシュしたら、自動的に ECS までデプロイできる環境を作ってみます。

参考ページ(公式ドキュメント)
https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/ecs-cd-pipeline.html

前提
ECR、ECS 環境は構築済みとします。以下を参考にしていただければと思います。
https://zenn.dev/ttani/articles/aws-ecs-setup

手順

ローカル環境にソースコードと Docker ファイルを用意する

次のようなフォルダ構成で作成します。

フォルダ構成
.
├ src
│ └ index.html
├ Dockerfile
└ buildspec.yml
index.htmlファイル内容
<h1>AutoDeployTest!</h1>
Dockerfileファイル内容
FROM 'nginx:latest'
RUN service nginx start
COPY src /usr/share/nginx/html
VOLUME /usr/share/nginx/html
buildspec.ymlファイル内容
version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws --version
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com
      - REPOSITORY_URI=<aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/samplerepo
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -t $REPOSITORY_URI:latest .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker images...
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - echo Writing image definitions file...
      - printf '[{"name":"container01","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
    files: imagedefinitions.json

<aws_account_id>部分には AWS アカウント ID を設定します。リージョンが違う場合はそこも変更します。
REPOSITORY_URIは ECR のリポジトリの URI を設定します。
container01の部分は、Docker イメージを参照するサービスのタスク定義のコンテナ名とします。

参考情報
buildspec.ymlcommandsのところで、リポジトリ URI を、REPOSITORY_URI=<aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/samplerepoで直接指定していますが、コミットされたブランチによって、デプロイ先環境を切り替えるような Pipeline を組む場合、本記載を行ごと削除して、CodePipeline 側の環境変数(CodeDeploy 側の環境変数ではない)でREPOSITORY_URIを定義することで、Pipeline 単位で使用するリポジトリを切り替えることができます。
またimagedefinitions.jsonに対して受け渡しているコンテナ名"name":"container01"についても、printf '[{"name":"%s","imageUri":"%s"}]' $CONTAINER_NAME $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.jsonのように書き換え、CodePipeline 側の環境変数CONTAINER_NAMEを定義して引き渡すようにすることで、動的に切り替えができます。

注意
ビルドプロセスの中で、docker Hub からイメージを PULL している場合、IP アドレス単位で時間当たりの PULL 数が制限されており、AWS の CodeBuild の IP アドレスが共有であるために、Limit に引っかかり PULL できない場合があります。その場合、CodeBuild で認証するプロセスを組み込む必要があります。
以下に対応方法を記載しましたので、参考にしてください。

https://zenn.dev/ttani/articles/aws-codebuild-docker-limit

GitHub リポジトリの作成

GitHub にてリポジトリを作成しておきます。

例:リポジトリ名:ecsautodeploytest

ローカルリポジトリの作成~初回プッシュ

ローカル環境で Git リポジトリを初期化して Remote に追加しておきます。

shell
git init
git add .
git commit -m "My first commit"
git branch -M main
git remote add origin https://github.com/[ユーザ名]/ecsautodeploytest.git
git push -u origin main

※GitHub リポジトリ URL は作成したリポジトリを設定してください。
 ※GitHub のユーザ名、E-mail、Personal Access Token などは必要に応じて設定します。

CodePipeline の設定を行う

  1. AWS コンソールからCodePilelineを選択します。
  2. パイプラインを作成するを押下します。
  3. 任意のパイプライン名を設定します。(例:ecsAutoDeployPipeline
  4. サービスロールは自動設定されるのでそのままにします。
  5. 次にを押下します。
  6. ソースプロバイダーとしてGitHub(バージョン2)を選択します。
  7. 接続するを押下し、任意の接続名を設定します。(例:GitHubConnection
  8. 接続を行い、GitHub 側の画面で認可を行います。
  9. 新しいアプリをインストールするを選択し、連携対象のリポジトリを選択します。
  10. 接続ボタンを押下します。
  11. リポジトリ名から、対象のリポジトリを選択します。(既に接続済みのものから選択できます)
  12. ブランチ名から、mainを選択します。
  13. 出力アーティファクト形式CodePipeline のデフォルトを選択します。
  14. ビルドステージを追加するで、AWS CodeBuildを選択し、プロジェクトを作成するを押下します。
    1. プロジェクト名に任意の名前を設定します。(例:ecsAutoDeployBuild
    2. 環境イメージマネージド型イメージを選択します。
    3. オペレーティングシステムAmazon Linux2を選択します。
    4. ランタイムStandardを選択します。
    5. イメージaws/codebuild/amazonlinux2-x86_64-standard:3.0を選択します。
    6. イメージのバージョン環境タイプはそのままにします。
    7. 特権付与にチェックを入れます。
    8. CloudWatch logsの設定を行います。(必要に応じて、CloudWatch 側でロググループを作成しておきます。ログストリームは任意の名前を設定しておくと自動的に生成されます。ビルドエラーでの調査時に詳細ログを見るためにログが必要になるので、設定して置いた方が良いです。)
    9. CodePipeline に進むを押下します。
  15. 次にを押下します。
  16. デプロイステージを追加するページで、デプロイプロバイダAmazon ECSに設定します。
  17. クラスター名でサービスを実行するクラスタを選択します。(既に構築済みである前提とします)
  18. サービス名で更新するサービスを選択します。
  19. 次にを押下します。
  20. 確認画面で、内容を確認し、パイプラインを作成するを押下します。

Amazon ECR 権限を CodeBuild ロールに追加する

  1. AWS コンソールでIAMからロールを選択します。
  2. 検索ボックスにcodebuild-と入力し、CodePipeline ウィザードによって作成されたロールを選択します。
  3. 許可ポリシーからアクセス許可の追加を押下し、ポリシーをアタッチを選択します。
  4. AmazonEC2ContainerRegistryPowerUserを選択し、ポリシーをアタッチを押下します。

動作確認

ソースを一部変更してコミットします。
CodePipeline の画面を開き、デプロイ状況をウォッチします。
ECS に反映されサービスが更新されれば成功です。

所感

ECS 構築は細かい設定値が多くて大変でしたが、そこまで作ってしまえば、割と手順通りに素直に設定するとスムーズに構築できます。

Discussion