1. はじめに
デプロイ作業の自動化を目的に、初めて GitHub Actions を試してみました。
本記事では、GitHub Actions 未経験のエンジニアが Azure Container Apps へのデプロイパイプラインを構築するまでに実施した手順や、技術的につまずいたポイントを中心に紹介します。
「まずは GitHub Actions を動かしてみたい」「Azure Container Apps のデプロイを自動化したい」と考えている方にとって、何かしらの手掛かりになれば幸いです。
2. 実現したかったこと
デプロイ作業の自動化という目的を達成するために、以下の内容に取り組みました。
- GitHub Actions でビルド〜デプロイを自動化する
- Azure Container Apps へのデプロイパイプラインを構築する
- dev / prod など環境ごとに設定を分離する
- 可能な限り単一の workflow で管理する
3. GitHub Actions をざっくり理解する
GitHub Actions は、GitHub 上でビルド・テスト・デプロイといった一連の処理を、イベント駆動で自動化するための実行基盤です。
リポジトリへの Push や Pull Request の作成、スケジュール実行など、さまざまなイベントをきっかけに 「どのジョブを、どの環境で、どのタイミングで実行するか」 を定義できます。
GitHub Actions は、以下の主要コンポーネントで構成されます。
| 用語 | 概要 |
|---|---|
| イベント(event) | ワークフローを 起動するきっかけ。push や pull_request など |
| ワークフロー(workflow) | 自動処理全体 の流れ。「いつ・何をするか」を定義する |
| ジョブ(job) | ワークフロー内の 処理のかたまり。順番または並列で実行される |
| ステップ(step) | ジョブの中の1つ1つの処理 |
| アクション(action) | 処理をまとめた 再利用可能 な部品 |
| ランナー(runner) | ジョブを実際に動かす 実行環境 |
これらは、次のような流れになります。
イベント(event) をきっかけに
ワークフロー(workflow) が起動し、
ジョブ(job) → ステップ(step) の順で処理が進み、
アクション(action) を使いながら、
ランナー(runner) 上で実行される。
4. 環境
今回の環境は、下図のとおりです。
アプリケーションは dev / prod で完全に分離された Azure Container Registry と Azure Container Apps にデプロイされる構成です。
5. 実際の workflow(抜粋)
workflow は、リポジトリ内の .github/workflows ディレクトリに置いたYAML ファイルとして定義します。
以下は、今回使った GitHub Actions の workflow の一部です。
5.1 以降では、全体像やそれぞれの処理内容について説明します。
name: Build and Deploy
on:
push:
tags:
- "dev*"
# 固定値だけで動作確認する
env:
ACR_NAME: yourAcrName # ex: mycompanyacr
ACA_NAME: yourContainerAppName # ex: my-app-dev
ACA_RESOURCE_GROUP: yourRgName # ex: rg-app-dev
DOCKERFILE_PATH: ./Dockerfile
# 実際の運用では以下のように構成要素(ACR_NAME や REPO_NAME 等)から動的に生成する
# ex: <ACR_NAME>.azurecr.io/<REPO_NAME>:<TAG>
IMAGE_FULL_NAME: yourAcrName.azurecr.io/yourRepoName:dev
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Login to ACR
run: |
az acr login --name "${{ env.ACR_NAME }}"
- name: Build Docker image
env:
DOCKERFILE_PATH: ${{ env.DOCKERFILE_PATH }}
run: |
docker build -f "$DOCKERFILE_PATH" -t "$IMAGE_FULL_NAME" .
- name: Push Docker image to ACR
run: |
docker push "$IMAGE_FULL_NAME"
- name: Deploy to Azure Container Apps
uses: azure/container-apps-deploy-action@v1
with:
acrName: ${{ env.ACR_NAME }}
containerAppName: ${{ env.ACA_NAME }}
resourceGroup: ${{ env.ACA_RESOURCE_GROUP }}
imageToDeploy: ${{ env.IMAGE_FULL_NAME }}
ここでは下記を省略しています
- dev / prod の環境分岐
- environment ごとの変数
- 条件分岐
最初から全部実現しようとせず、【まず1環境で動く → 次に環境を分ける】 という順番で進めるのがおすすめです。
azure/login などのアクションは、2026年2月時点のバージョンを採用しています。
実際の利用時には、GitHub Marketplaceや公式リポジトリで最新の情報をご確認ください。
5.1 全体像
この workflow(抜粋)は、次の処理を行います。
dev*タグの push をトリガーに workflow を開始する- コード取得・Azure ログインを行う(準備)
- Docker イメージをビルドする
- ビルドしたイメージを Azure Container Registry へ push する
- Azure Container Registry のイメージを Azure Container Apps へデプロイする
workflow / job / step の対応関係
本 workflow は、以下の階層構造で動作します。また、番号は上記処理と対応しています。
workflow(1)
└─ job: build-and-deploy(2)~(5)
├─ step: Checkout code(2)
├─ step: Azure Login(2)
├─ step: Login to ACR(2)
├─ step: Build Docker image(3)
├─ step: Push Docker image to ACR(4)
└─ step: Deploy to Azure Container Apps(5)
5.2 詳細
5.2.1 dev* タグの push をトリガーに workflow を開始する
workflow
on:
push:
tags:
- "dev*"
event 定義として、「いつこの workflow を動かすか」を決めています。
dev-2024-01-01dev-v1.0.0
のような tag を push すると、この workflow が実行されます。
5.2.2 コード取得・Azure ログインを行う(準備)
job: build-and-deploy
jobs:
build-and-deploy:
runs-on: ubuntu-latest
「ざっくりどのような処理を行うか、またどこで実行するか」 を決めています。
-
build-and-deployという job を1つ定義 - GitHub が用意してくれる
ubuntu-latestの runner 上で実行
今回はこの job の中で、ビルド → push → デプロイ までを一気に行います。
step: Checkout code
- name: Checkout code.
uses: actions/checkout@v6
以降は、step の定義として 「具体的にどのような処理を行うか」 を決めています。
ここでは、GitHub Actions 上に、リポジトリのコードを持ってきます。
ほぼすべての workflow で最初に出てくる定番の step です。
step: Azure Login / step: Login to ACR
# Azure ログイン
- name: Azure login.
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# Azure Container Registry ログイン
# 注: $ACR_NAME は今回省略した job で定義しています
- name: Login to ACR
run: |
az acr login --name "${{ env.ACR_NAME }}"
-
Azure CLI を使えるようにするためのログイン処理です
- 認証情報は GitHub Secrets に保存
- workflow には直接書かない
という形にしています。
-
Docker イメージを push するために、ACR にログインします
5.2.3 Docker イメージをビルドする
step: Build Docker image
- name: Build Docker image
env:
DOCKERFILE_PATH: ${{ env.DOCKERFILE_PATH }}
run: |
docker build -f "$DOCKERFILE_PATH" -t "$IMAGE_FULL_NAME" .
- コンテナイメージのビルドについて、今回はシンプルさを優先して
docker buildコマンドを採用しました - Docker社公式では
setup-buildx-actionとbuild-push-actionの組み合わせが提供されています
5.2.4 ビルドしたイメージを Azure Container Registry へ push する
step: Push Docker image to ACR.
- name: Push Docker image to ACR.
run: |
docker push "$IMAGE_FULL_NAME"
- この処理により、Azure Container Apps が参照できるイメージが Azure Container Registry に登録 されます
5.2.5 Azure Container Registry のイメージを Azure Container Apps へデプロイする
step: Deploy to Azure Container Apps.
- name: Deploy to Azure Container Apps
uses: azure/container-apps-deploy-action@v1
with:
acrName: ${{ env.ACR_NAME }}
containerAppName: ${{ env.ACA_NAME }}
resourceGroup: ${{ env.ACA_RESOURCE_GROUP }}
imageToDeploy: ${{ env.IMAGE_FULL_NAME }}
- Azure Container Registry に push された 最新のイメージを Azure Container Apps のアプリケーションに紐づけて更新 します
6. environments を使った環境分け
GitHub Environments を使うと、環境ごとに シークレット / 変数 / 承認ルール を切り替えられます。
今回は タグ名(dev / prod)から environment 名を判定し、その結果を後続 job に渡す 構成にしました。
特に今回は environment に承認フローを含めていたため、GitHub Environments を参照する job を1つに限定し、workflow 1回の実行につき承認を1回にしたい、という理由でこのような設計にしています。
6.1 環境分岐の全体フロー図
6.2 タグ名から environment を判定する job
まず、タグ名(dev-xxx / prod-xxx)をもとに デプロイ先の environment 名を決定します。
この job は「タグ名 → environment 名」の変換のみを行い、その結果を outputs として次の job に渡します。
実運用では3つ以上の複数環境(例:dev / staging / prod)を扱うため、環境判定は専用 job に集約しています。これにより、環境の追加やルール変更があっても、1箇所の修正で全体へ反映 できるようになりました。
jobs:
determine-environment:
runs-on: ubuntu-latest
outputs:
environment-name: ${{ steps.determine-env.outputs.environment_name }}
steps:
- id: determine-env
name: 環境名判定
env:
REF_NAME: ${{ github.ref_name }}
run: |
TARGET="${REF_NAME}"
case "$TARGET" in
dev*) echo "environment_name=dev" >> "$GITHUB_OUTPUT" ;;
prod*) echo "environment_name=prod" >> "$GITHUB_OUTPUT" ;;
*)
echo "::error:: 未対応のタグ: $TARGET"
exit 1
;;
esac
6.3 判定した environment を後続 job で利用
後続の job では、先ほど判定した environment_name をそのまま指定します。
build-and-deploy:
runs-on: ubuntu-latest
needs:
- determine-environment
environment:
name: ${{ needs.determine-environment.outputs.environment_name }}
env:
# Environment変数をここで読み込み、以降のステップで利用する.
ENV_NAME: ${{ vars.ENV_NAME }}
steps:
# 以下 前述の step
これにより
-
dev-*タグ → dev environment の Secrets / Variables -
prod-*タグ → prod environment の Secrets / Variables
を自動で切り替えてデプロイできます。
7. つまづいたポイント
YAMLやシェルスクリプトの書き方に慣れなかった
GitHub Actions を触り始めて一番最初につまずいたのが、YAML やシェルスクリプトの書き方そのものでした。
- YAMLのルール(設定ファイルの枠組み)
- インデント、
:、-の使い方。1マスのズレでエラーになる
- インデント、
- シェルスクリプトのルール(run: の中身)
-
case ... esacやifなど、Linuxサーバーを操作する「命令」
-
- GitHub Actions 独自のルール
-
${{ secrets.XXX }}やecho "... >> $GITHUB_OUTPUT"といった「専用の呪文」
-
といった点に、なかなか慣れませんでした。GitHub Actions が取っ掛かりづらいというよりは、「3つの異なる言語」が1つのファイルに混ざっていることがわかりづらかったです。
環境分けの考え方に悩んだ
環境分けについては、「どこまでを workflow で制御するか」という点で悩みました。
最終的には、環境ごとの差分はできるだけ GitHub Environments 側に寄せ、workflow は共通処理に集中させるかたちにしました。
8. まとめ
GitHub Actions を使って Azure Container Apps へデプロイし、環境分けまでを紹介しました。
今回は「まず自動でデプロイできる状態」を優先しましたが、今後は運用しながら、少しずつ改善していきたいと考えています。
GitHub Actions は最初とっつきにくかったですが、「小さく動かす」ことを目標にすると、理解しやすくなると感じました。
参考
We Are Hiring!
