バッチ処理をECSに移行した話(GitHubActionsもあるよ)その2
こんにちは、ハンズラボの清水です。東急ハンズのECサイトを担当しています。今回は前回の続き、GitHubのリポジトリにpushしたらECRへpushを行うGitHubActionsを紹介します。
前回の記事はこちら
バッチ処理をECSに移行した話(GitHubActionsもあるよ)その1
前回の記事の追記(Fargateになりました)
前回の記事のクラスターを作成にEC2を利用しましたが、その後、NATGatewayにElasticIPをつけることでFargateで出て行くIPアドレスを固定することができたのでFargateになりました。
IPアドレスを固定する理由は外部ECモール(yahoo, 楽天など)のAPIを利用する際、IPアドレスの制限があるのでIPを固定しています。
GitHubActionsを作成する
ここから本題!GitHubのリポジトリにpushしたらECRへpushを行うGitHubActionsを作成していきます。
参考にしたもの(https://github.com/actions/example-aws)
主な流れはこんな感じ
- GitHubのリポジトリにコードをpushする
- docker buildを行う
- dockerにタグをつける
- AWSのアカウントにログイン
- ECRにpushする
GitHubのリポジトリから作成します。
作成を行うとプロジェクト内に.github/main.workflowというファイルが作成されます。GitHubActionsのGUIで作成も出来ますし、main.workflowを編集して作成もできます。
個人的にはGUIで大まかな流れを作成して、main.workflowを編集するやり方が個人的には作成しやすいです。
main.workflowの見方
workflow "Build and Deploy(prod)" {
resolves = [ # 実行するAction
"Filters Branch(prod)",
"Slack Push Finish(prod)",
"Slack Push Start(prod)",
]
on = "push"
}
action "Filters Branch(prod)" {
uses = "actions/bin/filter@master"
args = "branch master" # ブランチがmasterの時のみ
}
action "Build Docker Image(prod)" {
uses = "actions/docker/cli@master"
# 環境変数
env = {
STAGE = "prod"
}
args = ["build", "-t", "test-python", ".", "--build-arg", "STAGE=$STAGE"] # dockerコマンドのargs
needs = ["Filters Branch(prod)"] # Filters Branch(prod)の後に実行
}
がっつりmain.workflowを書くことはありませんが、GUIである程度作成してしまえばいいので編集するのはenvやargsくらいです。
usesは使用するdocker imageです。(独自の環境での実行もできます)
作成したもの
各説明(処理の流れ)
1. ブランチをフィルタリングする
pushされたブランチがmasterの時のみ下に処理を流します。
GitHubActionsでは条件分岐ができないのでFillterを使用しています。
2. イメージのbuild, ECRへのログイン, slack通知
ここではイメージの build、ECRへのログイン、slackへの通知を並列で実行します。
action "Build Docker Image(prod)" {
uses = "actions/docker/cli@master"
env = {
STAGE = "prod"
}
args = ["build", "-t", "test-python", ".", "--build-arg", "STAGE=$STAGE"]
needs = ["Filters Branch(prod)"]
}
やっていることはdocker build -t test-python . –build-arg STAGE=$STAGEのコマンドを実行しています。
action "Login to ECR(prod)" {
uses = "actions/aws/cli@master"
args = "ecr get-login --no-include-email --region ap-northeast-1 | sh"
secrets = [
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
]
needs = ["Filters Branch(prod)"]
}
ECRへのログインも先ほどのdocker build同様にawsのコマンドを実行しています。secretsにAWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYをセットすることでECRにログインできます。
secretsの登録は割と簡単です。
action "Slack Push Start(prod)" {
uses = "Ilshidur/action-slack@master"
needs = ["Filters Branch(prod)"]
secrets = ["SLACK_WEBHOOK"]
args = "push開始(prod)"
}
slack通知はsecretsにwebhookのURLをセットしてargsにチャンネルに通知するメッセージを設定します。
3. dockerイメージにタグをつける
action "Tag image for ECR(prod)" {
uses = "actions/docker/tag@master"
env = {
CONTAINER_REGISTRY_PATH = "<アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com"
IMAGE_NAME = "test-python"
}
args = ["$IMAGE_NAME", "$CONTAINER_REGISTRY_PATH/$IMAGE_NAME"]
needs = ["Build Docker Image(prod)"]
}
docker tag test-python:latest <アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/hogehoge:latest
行なっていることは上記のコマンドと同じですコマンドではバージョンをlatestとしていますが、GitHubActionsではバージョンにブランチ名が適応されます。
4. ECRへpushする
action "Push image to ECR(prod)" {
uses = "actions/docker/cli@master"
needs = [
"Login to ECR(prod)",
"Tag image for ECR(prod)",
]
env = {
CONTAINER_REGISTRY_PATH = "<アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com"
IMAGE_NAME = "test-python"
}
args = ["push", "$CONTAINER_REGISTRY_PATH/$IMAGE_NAME"]
}
dockerイメージのタグ付け、ECRへのログインが終わり次第ECRへpushを行います。
docker push <アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/test-python:latest
行なっているコマンドは同じですがバージョンのlatestは今回masterになっています。ECSのタスク定義でイメージのURLをlatestにしている場合はmasterに変更しましょう。
5. 完了通知をslackに飛ばす
2. の工程で説明を行なっているので省略します。
masterへpushを行うと、リポジトリのActionsタブから実行ログを見ることができます。
GitHubActionsを使って見ての感想
良い点
- 作成が簡単
- 処理の流れが見やすい
- Dockerとの相性が良い
悪い点
- ブランチごとにActionsを定義できない
- 条件分岐が使用できない(失敗したら~~するとか)
- AWSの複数アカウントに対応できない(Keyを1セットしか登録できない)
現在GitHubActionsはPublicBetaなので今後の機能追加に期待しています。