前回のQiita
リポジトリ
解説
こちらにも記載しています。
https://github.com/oyne2561/aws_deploy_rails7.2.2/blob/main/READ_GITHUB_ACTIONS.md
Github ActionsのSercetsを作成
実際の.github/workflows/cicd.yml
# ワークフローの名前を設定
name: CI/CD Pipeline
# このワークフローがいつ実行されるかを定義
on:
push:
branches: [ main, develop ] # mainまたはdevelopブランチにプッシュされた時
# 環境変数の定義(全てのジョブで使用可能)
env:
AWS_REGION: ap-northeast-1 # AWSリージョン(東京)
ECR_REPOSITORY: todo-app-api # ECR(Docker画像保存場所)のリポジトリ名
ECS_SERVICE: todo-app-api-service # ECS(コンテナ実行環境)のサービス名
ECS_CLUSTER: todo-app-api-cluster # ECSクラスター名
ECS_TASK_DEFINITION: todo-app-api-task # ECSタスク定義名
# ジョブの定義(並列または順次実行される処理の単位)
jobs:
# 1つ目のジョブ:テスト実行
test:
runs-on: ubuntu-latest # Ubuntu最新版の仮想マシンで実行
# ステップの定義(順次実行される処理)
steps:
# Step 1: ソースコードをチェックアウト(取得)
- name: Checkout code
uses: actions/checkout@v4
# Step 2: Ruby環境のセットアップ
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.2.0 # Ruby 3.2.0を使用
bundler-cache: true # キャッシュを無効化して手動でbundle install
# Step 3: コード品質チェック(RuboCop)
- name: Run RuboCop (Lint)
run: bundle exec rubocop
# 2つ目のジョブ:デプロイ実行
deploy:
needs: test # testジョブが成功した場合のみ実行
runs-on: ubuntu-latest
# mainブランチへのプッシュの場合のみ実行
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
# Step 1: ソースコードをチェックアウト
- name: Checkout code
uses: actions/checkout@v4
# Step 2: AWS認証情報の設定
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# Step 3: Amazon ECRにログイン
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
# Step 4: Docker ImageをビルドしてECRにプッシュ
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }} # GitコミットのSHAをタグとして使用
run: |
# Docker画像をビルドしてECRにプッシュ
docker build -f Dockerfile.prod -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
# latestタグも付けてプッシュ
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
# 次のステップで使用するため、画像URIを出力
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
# Step 5: 現在のECSタスク定義をダウンロード
- name: Download task definition
run: |
aws ecs describe-task-definition --task-definition $ECS_TASK_DEFINITION \
--query taskDefinition > task-definition.json
# Step 5.5: タスク定義のアーキテクチャをX86_64に修正
- name: Fix task definition architecture
run: |
# JSONファイルでcpuArchitectureをX86_64に変更
jq '.runtimePlatform.cpuArchitecture = "X86_64"' task-definition.json > task-definition-fixed.json
# 修正されたファイルに置き換え
mv task-definition-fixed.json task-definition.json
# 確認のため修正内容を表示
echo "=== 修正されたruntimePlatform ==="
jq '.runtimePlatform' task-definition.json
# Step 6: タスク定義に新しいDocker Imageを設定
- 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: task-definition.json
container-name: todo-app-api
image: ${{ steps.build-image.outputs.image }}
# Step 7: ECSサービスに新しいタスク定義をデプロイ
- 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 # サービスが安定するまで待機
GitHub Actionsを実装時に遭遇したエラーの解決
問題の概要
GitHub Actions での Docker デプロイ時に、ローカル開発環境(Apple Silicon/ARM64)とデプロイ先(Intel/AMD x86_64)のアーキテクチャが異なることで発生するエラーについて解説します。
エラーの原因
GitHub Actions のランナーや ECS などのクラウド環境は通常 x86_64 アーキテクチャを使用しますが、ローカルの Apple Silicon Mac では ARM64(aarch64)アーキテクチャを使用します。この不整合により、以下のような問題が発生します:
- Bundle install 時のプラットフォーム不整合
- Docker イメージの実行時エラー
- ECS タスクの起動失敗
解決手順
1. Gemfile.lock のプラットフォーム追加
まず、ローカル環境で Gemfile.lock に x86_64-linux プラットフォームを追加します。
bundle lock --add-platform x86_64-linux
実行後の Gemfile.lock
PLATFORMS
aarch64-linux # ARM64(既存)
x86_64-linux # Intel/AMD 64bit(新規追加)
2. Dockerfile の修正
Docker ビルド時の bundle コマンドの順序が重要です。deployment モードを有効にする前にプラットフォームを追加する必要があります。
# ❌ 間違った順序(deploymentモードが先だとlockファイル変更不可)
RUN bundle config set --local deployment 'true' && \
bundle lock --add-platform x86_64-linux # エラー!
# ✅ 正しい順序
RUN bundle config set --local without 'development test' && \
bundle lock --add-platform x86_64-linux && \ # 先にプラットフォーム追加
bundle config set --local deployment 'true' && \ # 後でdeploymentモード
bundle install --jobs 4
重要なポイント:
-
deploymentモードではロックファイルの変更が禁止される - プラットフォーム追加は
deploymentモードを有効にする前に実行する -
withoutオプションで不要な gem グループを除外してビルド時間を短縮
3. ECS タスク定義のアーキテクチャ修正
GitHub Actions の CI/CD パイプラインで、ECS タスク定義のアーキテクチャを動的に修正します。
# cicd.yml の一部
- name: Fix task definition architecture
run: |
# JSONファイルでcpuArchitectureをX86_64に変更
jq '.runtimePlatform.cpuArchitecture = "X86_64"' task-definition.json > task-definition-fixed.json
# 修正されたファイルに置き換え
mv task-definition-fixed.json task-definition.json
# 確認のため修正内容を表示
echo "=== 修正されたruntimePlatform ==="
jq '.runtimePlatform' task-definition.json
注意点
- ローカルでの
bundle lock --add-platform実行後は、必ずGemfile.lockをコミットする - ECS 以外のデプロイ先でも同様のアーキテクチャ指定が必要な場合がある
- Docker のマルチプラットフォームビルドを使用する場合は、別途
docker buildxの設定が必要
まとめ
Apple Silicon Mac での開発が一般的になった現在、アーキテクチャ不整合は頻繁に発生する問題です。適切な順序でのプラットフォーム設定と、CI/CD パイプラインでの動的な修正により、スムーズなデプロイが実現できます。




