GitHub Actions による Docker イメージの自動ビルドとデプロイ解説

## はじめに

このワークフローは、Docker イメージを自動的にビルドし、GitHub Container Registry (ghcr.io) に公開するための GitHub Actions の設定です。特徴として、AMD64 と ARM64 の両方のアーキテクチャに対応したマルチプラットフォームビルドを実現しています。

## トリガー設定

```yaml
on:
  workflow_dispatch:  # 手動実行
  push:
    branches:
      - main         # mainブランチへのプッシュ
    tags:
      - 'v*'         # vで始まるタグのプッシュ
```

このワークフローは3つのタイミングで実行されます：
1. GitHub上での手動実行
2. mainブランチへのコードプッシュ時
3. バージョンタグ（v1.0.0など）のプッシュ時

## 権限とレジストリの設定

```yaml
permissions:
  contents: read
  packages: write

env:
  REGISTRY: ghcr.io
```

- `permissions`: GitHubリポジトリとパッケージに対する最小限の権限を設定
- `env`: GitHub Container Registry（ghcr.io）をレジストリとして使用

## build-and-pushジョブ：マルチプラットフォームビルド

```yaml
jobs:
  build-and-push:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        platform:
          - linux/amd64
          - linux/arm64
```

Ubuntu環境で実行され、matrixを使用して2つのアーキテクチャ（AMD64とARM64）向けのビルドを並行して行います。

### イメージ名の設定

```yaml
- name: Set image name
  run: |
    echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
    echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
  env:
    IMAGE_NAME: '${{ github.repository }}'
```

- リポジトリ名を小文字に変換（`${IMAGE_NAME,,}`）
- ghcr.ioのプレフィックスを追加してフルイメージ名を生成

### ビルド環境のセットアップ

```yaml
- name: Set up QEMU
  uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@v3

- name: Login to GitHub Container Registry
  uses: docker/login-action@v3
  with:
    registry: ${{ env.REGISTRY }}
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}
```

1. QEMUのセットアップ：クロスプラットフォームビルドを可能にする
2. Docker Buildxのセットアップ：マルチアーキテクチャビルドのための拡張機能
3. GitHub Container Registryへのログイン

### Docker メタデータとタグ設定

```yaml
- name: Extract Docker metadata
  id: meta
  uses: docker/metadata-action@v5
  with:
    images: ${{ env.FULL_IMAGE_NAME }}
    tags: |
      type=ref,event=branch
      type=semver,pattern={{version}}
      type=semver,pattern={{major}}.{{minor}}
      type=sha,prefix=git-
    flavor: |
      latest=${{ github.ref == 'refs/heads/main' }}
```

以下のタグ戦略を実装：
- ブランチ名ベースのタグ
- セマンティックバージョン（v1.0.0）
- メジャー.マイナーバージョン（v1.0）
- コミットハッシュベース（git-sha256...）
- mainブランチの場合はlatestタグも付与

### イメージのビルドとプッシュ

```yaml
- name: Build and push by digest
  uses: docker/build-push-action@v5
  id: build
  with:
    context: .
    push: true
    platforms: ${{ matrix.platform }}
    labels: ${{ steps.meta.outputs.labels }}
    outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
    cache-from: type=registry,ref=${{ env.FULL_IMAGE_NAME }}:buildcache-${{ env.PLATFORM_PAIR }}
    cache-to: type=registry,ref=${{ env.FULL_IMAGE_NAME }}:buildcache-${{ env.PLATFORM_PAIR }},mode=max
```

- `context`: ビルドコンテキストをカレントディレクトリに設定
- `platforms`: マトリックスで指定されたプラットフォーム向けにビルド
- `cache-from`/`cache-to`: レジストリベースのキャッシュを使用して、ビルド速度を向上
- `outputs`: イメージをダイジェスト形式でプッシュ

## merge-imagesジョブ：マルチアーキテクチャマニフェストの作成

```yaml
- name: Create and push manifest list
  working-directory: /tmp/digests
  run: |
    docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
      $(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
```

- 各アーキテクチャのイメージを統合
- マニフェストリストを作成してプッシュ
- すべてのタグを適用

このワークフローにより、以下が実現されます：
1. 複数アーキテクチャ対応のDockerイメージの自動ビルド
2. 効率的なキャッシュ管理
3. 柔軟なタグ付け
4. セキュアなイメージの配布

このような自動化により、開発者はコードに集中でき、デプロイメントプロセスの信頼性と効率性が向上します。

## リポジトリ

https://github.com/Sunwood-ai-labs/app-gallery-showcase/blob/main/.github/workflows/docker-image.yml

https://github.com/Sunwood-ai-labs/app-gallery-showcase