GitHub Actionsで本番環境と検証環境に異なるコンテナをpushする方法
この記事の目的
GitHub Actions を使ってコンテナを AWS Elastic Container Registry (ECR) に push する際、本番環境と検証環境で異なるコンテナを使い分けたいケースは多いと思います。
特に ECS Fargate で運用している場合、環境ごとに適切なタグを付けてイメージを管理することが重要になります。
本記事では、GitHub Actions で環境ごとに異なるコンテナを push する方法を解説します。
環境ごとに異なるコンテナを push する方法
本番環境と検証環境で異なるコンテナをデプロイするには、ブランチごとにタグを分けるのが一般的です。
タグのルールを決める
| ブランチ名 | 環境 | イメージタグ |
|---|---|---|
main |
本番環境 | my-image:prod |
develop |
検証環境 | my-image:staging |
feature/* |
開発環境 | my-image:dev |
GitHub Actions では GITHUB_REF という環境変数を使い、どのブランチで実行されているかを取得できます。
例えば、以下のような方法でブランチ名を取得できます。
- name: ブランチ名を取得
run: echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
GITHUB_REF には refs/heads/main のような値が入っているので、refs/heads/ の部分を削ることでブランチ名だけを取り出せます。Actions のログでは次のように出力されます。
Run echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
例えば main ブランチで実行した場合、BRANCH_NAME=main が環境変数にセットされます。
この BRANCH_NAME を使って、ECR に push するタグを動的に決めます。
GitHub Actions のワークフロー
以下は GitHub Actions を使って環境ごとに異なるコンテナを push するワークフローの例です。
name: Build and Push Docker Image
on:
push:
branches:
- main
- develop
- "feature/*"
env:
AWS_REGION: ap-northeast-1
ECR_REPOSITORY: my-container-repo
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: コードをチェックアウト
uses: actions/checkout@v3
- name: AWS CLI を設定
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 }}
- name: ECR にログイン
run: |
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin <AWS_ACCOUNT_ID>.dkr.ecr.$AWS_REGION.amazonaws.com
- name: ブランチ名を取得
run: echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
- name: イメージタグを決定
run: |
if [[ "$BRANCH_NAME" == "main" ]]; then
echo "IMAGE_TAG=prod" >> $GITHUB_ENV
elif [[ "$BRANCH_NAME" == "develop" ]]; then
echo "IMAGE_TAG=staging" >> $GITHUB_ENV
else
echo "IMAGE_TAG=dev" >> $GITHUB_ENV
fi
- name: Docker イメージをビルド
run: |
docker build -t $ECR_REPOSITORY:$IMAGE_TAG .
- name: ECR に push
run: |
docker tag $ECR_REPOSITORY:$IMAGE_TAG <AWS_ACCOUNT_ID>.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPOSITORY:$IMAGE_TAG
docker push <AWS_ACCOUNT_ID>.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPOSITORY:$IMAGE_TAG
「イメージタグを決定」ステップの Actions ログは、たとえば develop ブランチで実行した場合、次のようになります。
Run if [[ "$BRANCH_NAME" == "main" ]]; then
echo "IMAGE_TAG=prod" >> $GITHUB_ENV
elif [[ "$BRANCH_NAME" == "develop" ]]; then
echo "IMAGE_TAG=staging" >> $GITHUB_ENV
else
echo "IMAGE_TAG=dev" >> $GITHUB_ENV
fi
この結果、IMAGE_TAG=staging が環境変数にセットされ、以降のステップで my-container-repo:staging としてビルド・push されます。
Fargate でのデプロイ時のポイント
ECS タスク定義を環境ごとに更新する
ECS Fargate では task-definition.json を使ってコンテナ設定を更新できます。
環境ごとに適切なタグを適用するには、GitHub Actions でタスク定義を更新しましょう。
- name: タスク定義の更新
run: |
aws ecs update-service --cluster my-cluster \
--service my-service \
--force-new-deployment
ここで force-new-deployment を指定しているのがポイントです。このオプションを付けると、タスク定義やイメージが更新された際に確実に新しいコンテナへ切り替わります。
task-definition.json に変数を埋め込む方法
1. task-definition.json をテンプレート化する
環境変数を使うため、{{IMAGE_TAG}} のようなプレースホルダーを入れておきます。
{
"family": "my-task",
"containerDefinitions": [
{
"name": "my-app",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-container-repo:{{IMAGE_TAG}}",
"memory": 512,
"cpu": 256,
"essential": true
}
]
}
2. GitHub Actions で IMAGE_TAG を埋め込む
sed コマンドを使って、プレースホルダーを実際の値に置き換えます。
- name: `task-definition.json` に環境変数を埋め込む
run: |
sed -i 's/{{IMAGE_TAG}}/'"$IMAGE_TAG"'/g' task-definition.json
たとえば main ブランチで実行した場合、{{IMAGE_TAG}} が prod に置き換わり、イメージの指定が my-container-repo:prod になります。
まとめ
GitHub Actions で本番環境・検証環境ごとに異なるコンテナを push する方法を解説しました。
- ブランチごとにタグを分ける (
prod,staging,dev) - GitHub Actions でブランチを判定して自動で push する
-
task-definition.jsonに環境変数を埋め込んでタスク定義を動的に生成する - Fargate の
force-new-deploymentを活用して確実にデプロイを反映する
これらを組み合わせることで、環境ごとに適切なコンテナ管理ができ、デプロイの柔軟性が向上します。実際のプロジェクトに合わせてブランチ名やタグのルールを調整してみてください。
Discussion