T-CREATOR

GitHub Actions × DockerでCI/CD環境を構築するベストプラクティス

GitHub Actions × DockerでCI/CD環境を構築するベストプラクティス

GitHub ActionsとDockerを組み合わせると、コードのビルドから本番デプロイまでを一貫して自動化でき、開発速度と信頼性が大幅に向上します。
初心者の方にも分かりやすいよう、CI/CDの基本から応用テクニックまでを段階的に解説いたします。

GitHub ActionsとDocker連携

GitHub ActionsはGitHubリポジトリに直接組み込まれたCI/CDツールです。
Dockerと組み合わせることで、ビルド環境の再現性とポータビリティを担保しつつ、ワークフローを柔軟に構築できます。

ワークフロー全体像

以下のステップを順に実行し、コード変更から本番環境への反映までを自動化します。

ステップ処理内容
① Push/PR検知mainブランチへのpushやプルリクエストをトリガー
② イメージビルドDockerfileでアプリケーションをビルド
③ コンテナテストコンテナ内でユニットテストや静的解析を実行
④ レジストリPushDocker HubまたはGHCRへpush
⑤ デプロイSSHやWebhookを介して任意の環境にデプロイ

ワークフロー定義方法

ワークフローはリポジトリの .github/workflows/ci-cd.yml にYAML形式で記述します。
各ジョブやステップは独立して定義でき、必要に応じて並列実行や条件分岐も設定可能です。

yamlname: CI/CD Pipeline

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

公式参照Workflow syntax for GitHub Actions

ビルド&テスト工程

Docker Buildxを利用すれば、クロスプラットフォーム対応のビルドも容易です。
ビルド後は必ずコンテナ内で動作検証を行い、不具合を早期に発見しましょう。

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

      - name: Build Docker image
        run: docker build -t myapp:latest .

      - name: Run tests in container
        run: docker run --rm myapp:latest yarn test

シークレット管理

シークレット機能を使うと、APIキーや認証情報を安全に扱えます。
SecretsはGitHub上で暗号化され、ワークフロー外には露出しません。

yaml      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

公式参照docker/login-action

イメージタグ付けとプッシュ

ビルドごとにユニークなタグを自動生成し、過去のビルドと混同しない運用を実現します。
タイムスタンプベースのタグは一貫性があり、デバッグ時にも参照しやすくなります。

yaml      - name: Generate image tag
        id: tag
        run: echo "tag=$(date +%Y%m%d%H%M%S)" >> $GITHUB_OUTPUT

      - name: Build and push
        run: |
          docker build -t myapp:${{ steps.tag.outputs.tag }} .
          docker push myapp:${{ steps.tag.outputs.tag }}

GitHub Container Registry利用

GitHubネイティブのパッケージレジストリ「GHCR」を活用すると、組織単位でのアクセス制御やスキャンも容易です。
パブリック/プライベートリポジトリいずれにも対応し、GitHubエコシステムとシームレスに統合できます。

yaml      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Push to GHCR
        run: |
          docker tag myapp:${{ steps.tag.outputs.tag }} ghcr.io/${{ github.repository_owner }}/myapp:${{ steps.tag.outputs.tag }}
          docker push ghcr.io/${{ github.repository_owner }}/myapp:${{ steps.tag.outputs.tag }}

公式参照Publishing Docker images - GitHub Docs

キャッシュ最適化

Actionsのキャッシュ機能とBuildxのローカルキャッシュを組み合わせると、再ビルド時間を大幅に短縮できます。
依存ファイルや中間レイヤーをキャッシュし、差分のみを再構築する設計が鍵です。

yaml      - name: Cache Docker layers
        uses: actions/cache@v4
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-docker
          restore-keys: |
            ${{ runner.os }}-docker

      - name: Build with cache
        uses: docker/build-push-action@v5
        with:
          context: .
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache
          push: false

公式参照build-push-action with cache

自動デプロイ

サーバへのSSH実行や外部サービスのWebhookにより、デプロイを自動化できます。
任意のデプロイ手順をスクリプト化し、ボタン一つで最新環境へ反映可能です。

yaml      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.REMOTE_HOST }}
          username: ${{ secrets.REMOTE_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            docker pull myapp:latest
            docker stop myapp || true
            docker rm myapp || true
            docker run -d --name myapp -p 80:3000 myapp:latest

      - name: Notify via Webhook
        run: curl -X POST https://example.com/webhook -H "Authorization: Bearer ${{ secrets.DEPLOY_TOKEN }}"

マトリクスビルド

マトリクス戦略を使うと、複数バージョンやOSで同時にテスト・ビルドが可能となります。
これにより互換性を担保しつつ、CI時間を短縮できます。

yamlstrategy:
  matrix:
    node-version: [16, 18, 20]

steps:
  - uses: actions/setup-node@v3
    with:
      node-version: ${{ matrix.node-version }}
  - run: yarn install && yarn test

公式参照Matrix strategy

通知設定

ビルド成功・失敗をSlackやメールで通知し、チームへの情報共有を迅速化します。
通知対象やフォーマットは柔軟にカスタマイズ可能です。

yaml      - name: Notify Slack
        uses: slackapi/slack-github-action@v1
        with:
          payload: '{"text":"✅ デプロイ成功: ${{ github.sha }}"}'
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

Slack通知公式slackapi/slack-github-action

条件分岐設定

ブランチやファイルパスに応じたジョブ実行制御を設定し、不必要な実行を防ぎます。
また、手動トリガー(workflow_dispatch)で環境を指定して実行することも可能です。

yamlon:
  push:
    branches: [ main ]
    paths:
      - 'backend/**'
  workflow_dispatch:
    inputs:
      env:
        description: 'デプロイ先環境'
        required: true
        default: 'staging'

よくあるエラーと対処法

代表的なエラーとその解決策をまとめ、トラブルシュートを容易にします。

エラー内容原因対処
permission denied on SSH鍵の権限不足やホスト情報不一致chmod 600 で鍵の権限を修正
no space left on deviceビルド環境のディスク不足キャッシュクリアまたは別ランナーを使用
image not foundタグ名ミスやpush漏れdocker images で存在確認
docker: command not foundDocker未インストール環境runs-on: ubuntu-latest を指定

まとめ

  1. 連携全体像:Push検知からデプロイまでの自動化ワークフロー
  2. 基本構造.github/workflows 配下にYAMLで定義
  3. ビルド&テスト:Buildxとコンテナ内検証
  4. シークレット管理:安全な認証情報の運用
  5. タグ&プッシュ:ユニークタグ生成とレジストリ連携
  6. キャッシュ活用:ビルド高速化の鍵
  7. 自動デプロイ:SSH/Webhookで反映
  8. マトリクスビルド:並列テストで互換性担保
  9. 通知設定:Slack通知でチーム共有迅速化
  10. 条件分岐:実行範囲を最小化
  11. エラー対処:代表的障害と解決法

これらを組み合わせ、柔軟かつ信頼性の高いCI/CDパイプラインを構築してください。

公式ドキュメント

Dockerの記事Docker