G-gen の武井です。当記事では GitHub Actions を使って Docker イメージをビルド&プッシュして Cloud Run Jobs を更新するパイプランについて説明します。
GitHub Actions
概要
GitHub Actions とは、ソースコード管理ツールである GitHub に包含される機能の一つで、リポジトリで管理されるソースコードをもとに CI/CD (継続的インティグレーション / 継続的デリバリー) を実現します。
ワークフロー
GitHub Actions で自動化したい処理とその内容・条件を定義したものを ワークフロー と言います。
定義ファイルは YAML 形式 で記述して .github/workflows ディレクトリ に格納すれば利用可能です。
- 参考:ワークフローについて
構成
当記事で解説するパイプラインと環境構成は下図のとおりです。
Artifact Registry と Cloud Run Jobs は異なるプロジェクトで管理されるため、プロジェクトごとに Workload Identity を設定して GitHub Actions と連携します。
# | プロジェクト | 説明 |
---|---|---|
1 | demo-app-common-repo |
Artifact Registry でアプリが使用するイメージを一元管理 |
2 | sand1-demo-app-dev |
Cloud Run Jobs でアプリを実行 |
3 | sand2-demo-app-dev |
Cloud Run Jobs でアプリを実行 |
ワークフローの概要
今回ワークフローで定義した処理の概要は以下のとおりです。(詳細は後述)
- main ブランチへのマージをトリガーにワークフローが起動
- 指定のパス (アプリのソースコードが格納されたパス) の変更有無を確認
- 指定のパスに変更があった (アプリに更新があった) 場合、Docker イメージをビルドして Artifact Registry にプッシュ
- Cloud Run Jobs のイメージを更新する
ソースコード
概要
ソースコードは以下の形で構成されます。
.github/workflows
ディレクトリにはワークフローの定義ファイル、cloud_run_jobs_code
ディレクトリにはアプリごとのソースコードを格納します。
(アプリ名と Cloud Run Jobs のジョブ名は統一しています)
# アプリのソースコードの詳細は割愛
.
├── .github
│ └── workflows
│ ├── build-and-push.yaml
│ ├── dev-cd.yaml
│ └── release.yaml
├── cloud_run_jobs_code
│ ├── demo-app-1
│ │ ├── Dockerfile
│ │ ├── main.py
│ │ ├── poetry.lock
│ │ ├── poetry.toml
│ │ └── pyproject.toml
│ └── demo-app-2
│ ├── Dockerfile
│ ├── main.py
│ ├── poetry.lock
│ ├── poetry.toml
│ └── pyproject.toml
└── README.md
dev.yaml
処理内容
このワークフローでは、以下のモジュールを使用してアプリのソースコードが格納されたパスを指定し、それらの変更有無を確認します。
指定したパスに格納されるソースコード (アプリ) に変更があった場合は build-and-push.yaml
で処理を継続しますが、アプリに変更がない場合、ワークフローはここで終了します。
その他詳細は以下のとおりです。
# | 行数 | 説明 |
---|---|---|
1 | 3〜7行目 | main ブランチへのマージをトリガーに指定 |
2 | 9〜11行目 | ワークフローの権限定義 |
3 | 13〜29行目 | パスの指定、ならびに指定したパスの変更有無を確認 |
4 | 31〜37行目 | 変更があれば後続処理にアプリ名 (demo-app-1) を appName として渡す |
5 | 39〜45行目 | 変更があれば後続処理にアプリ名 (demo-app-2) を appName として渡す |
ファイル定義
name: Deploy to GCP development env on: push: branches: - main workflow_dispatch: permissions: id-token: write contents: read jobs: check-paths: runs-on: ubuntu-latest outputs: demo-app-1-changed: ${{ steps.filter.outputs.demo-app-1 }} demo-app-2-changed: ${{ steps.filter.outputs.demo-app-2 }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: list-files: shell filters: | demo-app-1: - 'cloud_run_jobs_code/demo-app-1/**' demo-app-2: - 'cloud_run_jobs_code/demo-app-2/**' demo-app-1: needs: check-paths if: >- needs.check-paths.outputs.demo-app-1-changed == 'true' uses: ./.github/workflows/build-and-push.yaml with: appName: 'demo-app-1' demo-app-2: needs: check-paths if: >- needs.check-paths.outputs.demo-app-2-changed == 'true' uses: ./.github/workflows/build-and-push.yaml with: appName: 'demo-app-2'
build-and-push.yaml
処理内容
このワークフローは dev.yaml から appName
が渡された (アプリに変更があった) 場合にのみ起動します。
そして、以下のモジュールを使用して各プロジェクトと Workload Identity で連携してタグ付き Docker イメージのビルド & プッシュと Cloud Run Jobs の更新を行います。
その他詳細は以下のとおりです。
# | 行数 | 説明 |
---|---|---|
1 | 3〜8行目 | appName のインプットをトリガーに指定 |
2 | 10〜26行目 | ランナーのセットアップ |
4 | 28〜30行目 | 環境変数の定義 |
4 | 32〜58行目 | demo-app-common-repo との WI 連携、Docker イメージのビルド&プッシュ |
5 | 60〜71行目 | sand1-demo-app-dev との WI 連携、Cloud Run Jobs の更新 |
5 | 60〜71行目 | sand2-demo-app-dev との WI 連携、Cloud Run Jobs の更新 |
ファイル定義
name: Build and push to GCP development env. on: workflow_call: inputs: appName: required: true type: string jobs: sdk: runs-on: ubuntu-latest steps: - name: 'Set up Cloud SDK' uses: 'google-github-actions/setup-gcloud@v2' with: version: '>= 363.0.0' build-and-push: runs-on: ubuntu-latest timeout-minutes: 300 needs: [sdk] permissions: id-token: write contents: read env: REPO: 'demo-app-common-repo-dev GAR: 'asia-northeast1-docker.pkg.dev/demo-app-common-repo' steps: - uses: actions/checkout@v4 - uses: google-github-actions/auth@v2 with: project_id: demo-app-common-repo workload_identity_provider: 'projects/1111111111/locations/global/workloadIdentityPools/demo-app-github-actions/providers/demo-app-github-actions' service_account: 'github@demo-app-common-repo.iam.gserviceaccount.com' - name: 'Set up app dir name' run: echo "APP_DIR=cloud_run_jobs_code/${{ inputs.appName }}" >> $GITHUB_ENV - name: 'Set up short sha' run: echo "SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-8)" >> "$GITHUB_ENV" - name: 'Set up app name variable' run: echo "IMAGE_NAME=${{ inputs.appName }}" >> "$GITHUB_ENV" - name: Build and Push image to Google Cloud Artifact Registry run: | gcloud auth configure-docker asia-northeast1-docker.pkg.dev --quiet docker build --platform linux/amd64 -t "${REPO}/${IMAGE_NAME}" ${APP_DIR} docker tag "${REPO}/${IMAGE_NAME}:latest" "${GAR}/${REPO}/${IMAGE_NAME}:latest" docker push "${GAR}/${REPO}/${IMAGE_NAME}:latest" docker tag "${REPO}/${IMAGE_NAME}:latest" "${GAR}/${REPO}/${IMAGE_NAME}:${SHORT_SHA}" docker push "${GAR}/${REPO}/${IMAGE_NAME}:${SHORT_SHA}" - uses: 'google-github-actions/auth@v2' with: project_id: sand1-demo-app-dev workload_identity_provider: 'projects/2222222222/locations/global/workloadIdentityPools/demo-app-github-actions/providers/demo-app-github-actions' service_account: 'github@sand1-demo-app-dev.iam.gserviceaccount.com' - name: Deploy to Cloud Run (sand1-demo-app-dev) uses: 'google-github-actions/deploy-cloudrun@v2' with: job: ${{ env.IMAGE_NAME }} image: ${{ env.GAR }}/${{ env.REPO }}/${{ env.IMAGE_NAME}}:latest region: 'asia-northeast1' - uses: 'google-github-actions/auth@v2' with: project_id: sand2-demo-app-dev workload_identity_provider: 'projects/3333333333/locations/global/workloadIdentityPools/demo-app-github-actions/providers/demo-app-github-actions' service_account: 'github@sand2-demo-app-dev.iam.gserviceaccount.com' - name: Deploy to Cloud Run (sand2-demo-app-dev) uses: 'google-github-actions/deploy-cloudrun@v2' with: job: ${{ env.IMAGE_NAME }} image: ${{ env.GAR }}/${{ env.REPO }}/${{ env.IMAGE_NAME}}:latest region: 'asia-northeast1'
インフラ構成
Workload Identity
今回の構成では、GitHub Actions との連携に Workload Identity を用いています。
設定方法の説明は割愛しますが、以下の記事の Workload Identiry 連携の設定
にならい同様の設定をします。
その際、Workload Identity に紐づけるサービスアカウントには以下の権限を付与します。
# | プロジェクト | 付与する権限 |
---|---|---|
1 | demo-app-common-repo | Artifact Registry 書き込み |
2 | sand1-demo-app-dev | Cloud Run デベロッパー |
3 | sand2-demo-app-dev | Cloud Run デベロッパー |
Artifact Registry
今回の構成では、Artifact Registry と Cloud Run Jobs が異なるプロジェクトに配置されています。
他のプロジェクトの Docker イメージをデプロイする場合、以下にならい Cloud Run サービス エージェント
に対して権限を付与します。
サービスエージェントについては以下の記事で説明しています。
動作確認
条件
demo-app-1
と demo-app-2
のソースコードを編集して main ブランチにマージした際の動作を確認します。
main ブランチへのマージとワークフローの起動
main ブランチにマージをするとワークフロー (dev.yaml
) が起動します。
demo-app-1
と demo-app-2
を更新したため、check-paths
ジョブで変更を検知して後続の build-and-push.yaml
にアプリ名を渡しています。
後続のワークフローの起動
アプリ名が渡され、次のワークフロー (build-and-puysh.yaml
) が起動します。
今回は2つのアプリが更新されたので、それぞれのアプリイメージをビルド&プッシュし、各プロジェクトの Cloud Run Jobs を更新するフローが走ります。
Docker イメージのビルドとプッシュ
demo-app-1
と demo-app-2
の Docker イメージ (タグ付き) がビルドされリポジトリにプッシュされました。
Cloud Run Jobs の更新
Docker イメージがリポジトリにプッシュされると、各プロジェクトで稼働する Cloud Run Jobs が gcloud run jobs deploy
コマンドで最新のタグ付きイメージに更新されました。
Cloud Logging にも google.cloud.run.v1.Jobs.ReplaceJob
メソッドにより Cloud Run Jobs が更新された旨が記録されていました。
関連記事
武井 祐介 (記事一覧)
クラウドソリューション部所属。G-gen唯一の山梨県在住エンジニア
Google Cloud Partner Top Engineer 2025 選出。IaC や CI/CD 周りのサービスやプロダクトが興味分野です。
趣味はロードバイク、ロードレースやサッカー観戦です。
Follow @ggenyutakei