CI/CDにはJenkinsやCircleCIもありますが、
GitHubActionsというものを知り、GitHubを使っているならソースコードとの整合性も保てて便利じゃないかと思いまして、早速導入することにしました。
今回は、GitHubActionsでDockerをビルドしてECSクラスタにさくっとデプロイしてみます。
1.ECSクラスターを作成する
ECSクラスターを作ってください。
※このなかではクラスタ名は、「development」としています。
2.ECRを作成する
DockerのImageを登録するためのECRを作成してください。
このなかではECRのリポジトリ名は、「development」としています。
3.Dockerfileを作成する
例えば、下記のようなPHPを動作させるコンテナをDockerfileを作ります。
/deploy/development/docker/php/Dockerfile
FROM php:7.4-fpm-alpine
# JSTに変更
RUN apk add tzdata && \
cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
# PHP などインストール
RUN set -eux \
&& apk add --update --no-cache git autoconf g++ libtool make libzip-dev libpng-dev libjpeg-turbo-dev freetype-dev oniguruma-dev libxml2-dev sed nginx redis \
&& pecl install redis \
&& docker-php-ext-configure gd --with-jpeg=/usr/include/ --with-freetype=/usr/include/ \
&& docker-php-ext-configure opcache --enable-opcache \
&& docker-php-ext-install opcache pdo_mysql gd zip mbstring xml \
&& docker-php-ext-enable redis \
&& apk del autoconf g++ libtool make \
&& rm -rf /tmp/*
#フォルダコピー
COPY ./ /var/www/html
# 作業ディレクトリを変更
WORKDIR /var/www/html
#パーミッション変更
RUN chown -R www-data:www-data /var/www/html
#コンテナ起動時にphp-fpmとnginx実行
CMD php-fpm -D && nginx -g 'daemon off;'
4.AWSでデプロイ用IAMを作成する
AWSで、ECSにデプロイさせるためにIAMユーザーを作ります。
下記の2つのパーミッションポリシーが必要です。
・AmazonEC2ContainerRegistryFullAccess
・AmazonEC2ContainerServiceFullAccess
5.GitHubのActions secretsにAWSのデプロイ用IAMのアクセスキー・シークレットキーを設定する
GitHubのレポジトリー→「Settings」→「Secrets」でAWSのデプロイ用アクセスキーを「AWS_ACCESS_KEY_ID」・シークレットキーを「AWS_SECRET_ACCESS_KEY」として登録します。
6.ECSクラスタのタスク定義jsonを作成する
ECSのタスク定義は、jsonファイルを作成してawscliでアップしておきましょう。
{
"requiresCompatibilities": [
"EC2"
],
"inferenceAccelerators": [],
"containerDefinitions": [
{
"name": "development",
"image": "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/development:latest",
"memoryReservation": 350,
"resourceRequirements": [],
"essential": true,
"portMappings": [
{
"hostPort": 0,
"containerPort": 80,
"protocol": "tcp"
}
],
"environment": [],
"environmentFiles": [],
"secrets": [],
"mountPoints": [],
"volumesFrom": [],
"extraHosts": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/development",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
},
"ulimits": [],
"dockerLabels": {},
"dependsOn": []
}
],
"volumes": [],
"networkMode": "bridge",
"placementConstraints": [],
"family": "development",
"taskRoleArn": "arn:aws:iam::xxxxxxxxxxxx:role/ecsTaskExecutionRole"
}
次のコマンドで、awscliでECSクラスタにタスクをアップしておきます。
aws ecs register-task-definition --cli-input-json file://./deploy/development/ecs/ecs-task-definition.json --profile hogehogeplofile
※hogehogeplofileはawscliのプロファイル。ご自分のプロファイルをお使いください。
7.ECSクラスタのサービスを作る
6のタスク定義をつかったサービスを作ってください。
jsonファイルを作成してawscliでアップでも良いですし、AWSコンソールからでも良いです。
8.GitHubActionsのWorkflow構成YAMLファイルを書く
on:
push:
branches:
- development
name: Deploy to AmazonECS(development) from development branch
jobs:
deploy:
name: Deploy app
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Configure AWS Credentials # AWSアクセス権限設定
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 # ECRログイン処理
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR # ECRイメージPush
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: development
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f ./deploy/development/docker/php/Dockerfile .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
- name: Render Amazon ECS task definition # ECSタスク定義ファイルレンダリング
id: render-container
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: deploy/development/ecs/ecs-task-definition.json # レポジトリ以下のタスク定義ファイルがあるPath
container-name: development
image: ${{ steps.build-image.outputs.image }}
- name: Deploy to Amazon ECS service # ECSサービスデプロイ
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-container.outputs.task-definition }}
service: development-web
cluster: development-cluster
このコードがGitHubActionsの設定ファイルです。
条件:developmentにPushされたときに下記内容を順次実行します。
①AWSアクセス権限設定
②ECRログイン処理
③DockerfileよりビルドしてDockerImageを作成してECRにPush
④ECSタスク定義を再修正
⑤ECSにタスク定義を使ってデプロイ
9.ソースをCommitしてGitHubにPushしてPullRequestを出します。
それでは用意ができたので、Gitで別ブランチでコミットしてください。
そして、GitHubにPushしてPullRequest出しておきましよう。
10.PullRequestでマージして、GitHubActions実行
別ブランチ→developmentブランチにマージした瞬間にGitHubActionsが実行されます。
GitHubリポジトリの「Actions」タブを開くと実行状況が確認できます。
11.ECSのローリングアップデートが終わるまで待つ
GitHubActionsで成功したら、ECSクラスタでローリングアップデートが始まりますので、新しいコンテナになるまで待ちましょう。