STEP 23:CI/CD統合(GitHub Actions)

🚀 STEP 23: CI/CD統合(GitHub Actions)

自動ビルド・テスト・デプロイのパイプライン構築

📋 このステップで学ぶこと

  • CI/CDとは何か
  • GitHub ActionsでDockerイメージビルド
  • Docker Hubへの自動プッシュ
  • タグ戦略(latest、バージョン番号)
  • セキュリティスキャン(Trivy)
  • 実践演習:完全なCI/CDパイプライン構築

🔧 0. このステップの前提知識

📚 これまでの学習の復習
  • Dockerfile:イメージのビルド(STEP 11-14)
  • Docker Hub:イメージの取得とプッシュ(STEP 7)
  • 環境変数:シークレット管理(STEP 21)
  • Git基礎:コミット、プッシュ、ブランチ

0-1. 作業ディレクトリの準備

mkdir -p ~/docker-practice/step23 cd ~/docker-practice/step23 pwd

0-2. CI/CDパイプラインの全体像

【CI/CDパイプライン フロー】 ┌─────────────────────────────────────────────────────────────────────┐ │ 開発者のローカル環境 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ コード編集 │───→│ テスト実行 │───→│ git push │ │ │ └──────────┘ └──────────┘ └─────┬────┘ │ └──────────────────────────────────────────┼──────────────────────────┘ │ ↓ トリガー ┌─────────────────────────────────────────────────────────────────────┐ │ GitHub Actions (CI) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ checkout │───→│ test │───→│ build │───→│ scan │ │ │ │ コード │ │ 自動テスト│ │イメージ構築│ │脆弱性検査 │ │ │ └──────────┘ └──────────┘ └──────────┘ └─────┬────┘ │ └────────────────────────────────────────────────────────┼────────────┘ │ ↓ 成功時 ┌─────────────────────────────────────────────────────────────────────┐ │ GitHub Actions (CD) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ push │───→│ deploy │───→│ notify │ │ │ │Docker Hub│ │ 本番反映 │ │ Slack通知│ │ │ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────────────────┘

0-3. GitHub Actionsの構成要素

要素説明
Workflow自動化プロセス全体.github/workflows/ci.yml
Eventワークフローを起動するトリガーpush, pull_request, schedule
Jobワークフロー内の処理単位build, test, deploy
Stepジョブ内の個別タスクcheckout, run, uses
Action再利用可能な処理actions/checkout@v3
Runnerワークフローを実行するサーバーubuntu-latest

0-4. 必要なアカウント

🔑 事前に必要なもの
  • GitHubアカウント:リポジトリとActions
  • Docker Hubアカウント:イメージの保存先
  • Docker Hubアクセストークン:自動プッシュ用

🎯 1. CI/CDとは

1-1. CI(Continuous Integration)継続的インテグレーション

【CIの流れ】 開発者A ───┐ │ 開発者B ───┼───→ リポジトリ ───→ 自動ビルド ───→ 自動テスト │ (main) ↓ ↓ 開発者C ───┘ 成功/失敗 成功/失敗 ↓ ↓ 即座に通知 即座に通知 【CIの利点】 ✅ コードの品質を維持 ✅ バグの早期発見 ✅ チーム開発の効率化 ✅ マージ前に問題を検出

1-2. CD(Continuous Deployment)継続的デプロイ

【CDの流れ】 テスト成功 ───→ ステージング環境 ───→ 承認 ───→ 本番環境 にデプロイ (自動/手動) にデプロイ 【CDの利点】 ✅ デプロイの自動化 ✅ リリース頻度の向上 ✅ 人的ミスの削減 ✅ ロールバックの容易化

1-3. GitHub Actionsの特徴

💰 無料枠あり

パブリックリポジトリは無料
プライベートは月2,000分まで無料

⚡ 簡単設定

YAMLファイル1つで設定
GitHub完全統合

🔧 豊富なアクション

マーケットプレイスで
数千のアクションを利用可能

🔗 GitHub統合

PR、Issue、リリースと連携
ステータスチェック

🔧 2. GitHub Actionsの基本

2-1. プロジェクト構造

# ディレクトリ構造を作成 mkdir -p .github/workflows # 構造 # myproject/ # ├── .github/ # │ └── workflows/ # │ ├── docker-build.yml # ビルドワークフロー # │ └── docker-publish.yml # プッシュワークフロー # ├── Dockerfile # ├── requirements.txt # └── app.py

2-2. 最小構成のワークフロー

# ワークフローファイルを作成 cat > .github/workflows/docker-build.yml << ‘EOF’ # ワークフローの名前 name: Docker Build # トリガー:いつ実行するか on: push: branches: [ main ] # mainブランチへのプッシュ時 pull_request: branches: [ main ] # mainへのPR作成時 # ジョブ:実行する処理 jobs: build: runs-on: ubuntu-latest # 実行環境 steps: # ステップ1: コードをチェックアウト – name: Checkout code uses: actions/checkout@v3 # ステップ2: Dockerイメージをビルド – name: Build Docker image run: | docker build -t myapp:test . # ステップ3: 簡単なテスト – name: Test Docker image run: | docker run –rm myapp:test python -c “print(‘Hello CI/CD!’)” EOF cat .github/workflows/docker-build.yml

2-3. ワークフローの構成要素

【ワークフローの構造】 name: ワークフロー名 ← GitHubのActionsタブに表示 │ on: トリガー ← いつ実行するか │ ├── push: プッシュ時 │ ├── pull_request: PR時 │ ├── schedule: 定期実行(cron形式) │ └── workflow_dispatch: 手動実行 │ jobs: ← 実行する処理群 │ └── build: ← ジョブ名 │ ├── runs-on: ubuntu-latest ← 実行環境 │ └── steps: ← 個別の処理 ├── uses: アクションを使用 └── run: シェルコマンドを実行

2-4. よく使うトリガー

トリガー説明
pushプッシュ時branches: [main]
pull_requestPR作成/更新時branches: [main]
schedule定期実行cron: '0 0 * * *'
workflow_dispatch手動実行ボタンクリックで実行
releaseリリース時types: [published]

📦 3. Docker Hubへの自動プッシュ

3-1. シークレットの設定

🔐 GitHubのシークレット設定手順
  1. GitHubリポジトリの「Settings」タブを開く
  2. 左メニューの「Secrets and variables」→「Actions」を選択
  3. 「New repository secret」をクリック
  4. 以下の2つを追加:
    • DOCKERHUB_USERNAME:Docker Hubのユーザー名
    • DOCKERHUB_TOKEN:Docker Hubのアクセストークン
⚠️ Docker Hubアクセストークンの取得方法
  1. Docker Hub(https://hub.docker.com)にログイン
  2. 右上のアカウント → Account Settings
  3. Security → New Access Token
  4. 名前を入力(例:github-actions)
  5. 「Generate」をクリック
  6. 表示されたトークンをコピー(一度しか表示されない!)

3-2. Docker Hub自動プッシュワークフロー

cat > .github/workflows/docker-publish.yml << ‘EOF’ name: Docker Publish on: push: branches: [ main ] tags: – ‘v*’ # v1.0.0 のようなタグ env: IMAGE_NAME: myapp jobs: build-and-push: runs-on: ubuntu-latest steps: # コードをチェックアウト – name: Checkout code uses: actions/checkout@v3 # Docker Buildxをセットアップ(マルチプラットフォーム対応) – name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 # Docker Hubにログイン – name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} # メタデータを抽出(タグ生成) – name: Extract metadata id: meta uses: docker/metadata-action@v4 with: images: ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=semver,pattern={{version}} type=sha # ビルドしてプッシュ – name: Build and push uses: docker/build-push-action@v4 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max EOF

3-3. タグ戦略

【自動生成されるタグ】 ┌─────────────────────────────────────────────────────────────────────┐ │ トリガー 生成されるタグ │ ├─────────────────────────────────────────────────────────────────────┤ │ git push origin main → username/myapp:main │ │ → username/myapp:sha-abc1234 │ ├─────────────────────────────────────────────────────────────────────┤ │ git tag v1.2.3 → username/myapp:1.2.3 │ │ git push –tags → username/myapp:1.2 │ │ → username/myapp:latest │ ├─────────────────────────────────────────────────────────────────────┤ │ Pull Request #123 → username/myapp:pr-123 │ └─────────────────────────────────────────────────────────────────────┘

🔒 4. セキュリティスキャン(Trivy)

4-1. Trivyとは

Trivyは、コンテナイメージの脆弱性をスキャンするオープンソースツールです。 OSパッケージやアプリケーション依存関係の脆弱性を検出します。

【Trivyの検出対象】 ┌─────────────────────────────────────────────────────────────────────┐ │ Dockerイメージ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ アプリケーション層 │ │ │ │ └─ Python/Node.js/Java等の依存関係 ← 脆弱性チェック │ │ │ ├─────────────────────────────────────────────────────────────┤ │ │ │ OSパッケージ層 │ │ │ │ └─ apt/yum等でインストールしたパッケージ ← 脆弱性チェック │ │ │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ベースイメージ │ │ │ │ └─ Ubuntu/Alpine等のOS ← 脆弱性チェック │ │ │ └─────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘

4-2. Trivyスキャンワークフロー

cat > .github/workflows/security-scan.yml << ‘EOF’ name: Security Scan on: push: branches: [ main ] schedule: – cron: ‘0 0 * * 0’ # 毎週日曜日の0時(UTC) jobs: scan: runs-on: ubuntu-latest steps: – name: Checkout code uses: actions/checkout@v3 – name: Build image for scanning run: docker build -t myapp:scan . – name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: ‘myapp:scan’ format: ‘table’ exit-code: ‘1’ # 脆弱性発見時は失敗 ignore-unfixed: true # 修正不可なものは無視 severity: ‘CRITICAL,HIGH’ # 重大度の高いもののみ – name: Run Trivy and output SARIF uses: aquasecurity/trivy-action@master if: always() with: image-ref: ‘myapp:scan’ format: ‘sarif’ output: ‘trivy-results.sarif’ – name: Upload scan results uses: github/codeql-action/upload-sarif@v2 if: always() with: sarif_file: ‘trivy-results.sarif’ EOF

4-3. Trivyの設定オプション

オプション説明推奨値
exit-code脆弱性発見時の終了コード‘1’(失敗させる)
severityチェックする重大度‘CRITICAL,HIGH’
ignore-unfixed修正不可能な脆弱性を無視true
format出力形式‘table’ or ‘sarif’

🛠️ 5. 完全なCI/CDパイプライン

5-1. サンプルアプリケーションの作成

# Flaskアプリを作成 cat > app.py << ‘EOF’ from flask import Flask, jsonify app = Flask(__name__) @app.route(‘/’) def hello(): return jsonify({‘message’: ‘Hello CI/CD!’, ‘status’: ‘ok’}) @app.route(‘/health’) def health(): return jsonify({‘status’: ‘healthy’}) if __name__ == ‘__main__’: app.run(host=’0.0.0.0′, port=5000) EOF # 依存関係ファイル cat > requirements.txt << ‘EOF’ flask==2.3.0 pytest==7.4.0 EOF # テストファイル mkdir -p tests cat > tests/test_app.py << ‘EOF’ import pytest from app import app @pytest.fixture def client(): app.config[‘TESTING’] = True with app.test_client() as client: yield client def test_hello(client): response = client.get(‘/’) assert response.status_code == 200 assert b’Hello CI/CD!’ in response.data def test_health(client): response = client.get(‘/health’) assert response.status_code == 200 assert b’healthy’ in response.data EOF

5-2. Dockerfileの作成

cat > Dockerfile << ‘EOF’ FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install –no-cache-dir -r requirements.txt COPY . . EXPOSE 5000 HEALTHCHECK –interval=30s –timeout=3s \ CMD curl -f http://localhost:5000/health || exit 1 CMD [“python”, “app.py”] EOF

5-3. 統合CI/CDワークフロー

cat > .github/workflows/ci-cd.yml << ‘EOF’ name: CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main ] release: types: [ published ] env: DOCKER_IMAGE: ${{ secrets.DOCKERHUB_USERNAME }}/myapp jobs: # ジョブ1: テスト test: runs-on: ubuntu-latest steps: – uses: actions/checkout@v3 – name: Set up Python uses: actions/setup-python@v4 with: python-version: ‘3.9’ – name: Install dependencies run: | pip install -r requirements.txt – name: Run tests run: pytest tests/ -v # ジョブ2: ビルドとスキャン build-and-scan: needs: test runs-on: ubuntu-latest steps: – uses: actions/checkout@v3 – name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 – name: Build image uses: docker/build-push-action@v4 with: context: . load: true tags: ${{ env.DOCKER_IMAGE }}:test – name: Run Trivy scan uses: aquasecurity/trivy-action@master with: image-ref: ${{ env.DOCKER_IMAGE }}:test format: ‘table’ exit-code: ‘0’ severity: ‘CRITICAL,HIGH’ # ジョブ3: プッシュ(mainブランチのみ) push: needs: build-and-scan if: github.ref == ‘refs/heads/main’ runs-on: ubuntu-latest steps: – uses: actions/checkout@v3 – name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 – name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} – name: Extract metadata id: meta uses: docker/metadata-action@v4 with: images: ${{ env.DOCKER_IMAGE }} tags: | type=ref,event=branch type=sha type=raw,value=latest – name: Build and push uses: docker/build-push-action@v4 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} cache-from: type=gha cache-to: type=gha,mode=max # ジョブ4: デプロイ通知 notify: needs: push if: success() runs-on: ubuntu-latest steps: – name: Send notification run: | echo “✅ Deployment successful!” echo “Image: ${{ env.DOCKER_IMAGE }}:latest” EOF

5-4. 実行の流れ

# 1. ローカルでテスト pytest tests/ -v # 2. コードをコミット・プッシュ git add . git commit -m “Add CI/CD pipeline” git push origin main # 3. GitHubでActionsタブを確認 # → テスト → ビルド → スキャン → プッシュ の順で実行される # 4. Docker Hubでイメージを確認 # https://hub.docker.com/r/username/myapp/tags

🔧 6. トラブルシューティング

6-1. よくある問題と対処法

問題1: ワークフローが実行されない
  • ファイルパスを確認:.github/workflows/に配置されているか
  • YAML構文エラーがないか確認
  • ブランチ名がon:で指定したものと一致しているか
問題2: Docker Hubへのプッシュが失敗
  • シークレットが正しく設定されているか確認
  • DOCKERHUB_USERNAMEDOCKERHUB_TOKENの名前を確認
  • Docker Hubのアクセストークンが有効か確認
# シークレットの確認方法 # Settings → Secrets and variables → Actions # シークレット名に typo がないか確認
問題3: テストが失敗する
  • ローカルでテストが通るか確認
  • 依存関係がすべてrequirements.txtに含まれているか
  • Pythonバージョンが一致しているか

6-2. デバッグ方法

# ワークフローにデバッグステップを追加 – name: Debug info run: | echo “Branch: ${{ github.ref }}” echo “Event: ${{ github.event_name }}” echo “SHA: ${{ github.sha }}” ls -la cat Dockerfile

💪 7. 練習問題

練習問題 1 基礎

CI/CDの利点を3つ挙げてください。

  1. 品質向上:自動テストでバグを早期発見
  2. 効率化:手動作業の削減、デプロイの自動化
  3. リスク軽減:小さな変更を頻繁にデプロイ、問題の切り分けが容易
練習問題 2 基礎

GitHub Actionsのワークフローファイルはどこに配置しますか?

.github/workflows/ ディレクトリ内に.ymlまたは.yamlファイルとして配置します。

myproject/ └── .github/ └── workflows/ └── ci.yml
練習問題 3 基礎

mainブランチへのpush時にのみ実行されるトリガーを書いてください。

on: push: branches: [ main ]
練習問題 4 応用

GitHubシークレットをワークフロー内で参照する方法を書いてください。

${{ secrets.シークレット名 }}の形式で参照します。

– name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }}
練習問題 5 応用

テストが成功した後にのみビルドジョブを実行する設定を書いてください。

needs:キーワードを使用して依存関係を指定します。

jobs: test: runs-on: ubuntu-latest steps: – run: pytest build: needs: test # testジョブが成功した後に実行 runs-on: ubuntu-latest steps: – run: docker build .
練習問題 6 応用

Trivyでセキュリティスキャンを行い、CRITICAL脆弱性がある場合にワークフローを失敗させる設定を書いてください。

– name: Run Trivy scan uses: aquasecurity/trivy-action@master with: image-ref: ‘myapp:latest’ exit-code: ‘1’ # 脆弱性発見時に失敗 severity: ‘CRITICAL’ # CRITICALのみチェック
練習問題 7 発展

毎日午前3時(UTC)に実行されるスケジュールトリガーを書いてください。

on: schedule: – cron: ‘0 3 * * *’ # 分 時 日 月 曜日 # 毎日午前3時(UTC)に実行

cron形式:分 時 日 月 曜日

練習問題 8 発展

mainブランチの場合のみDocker Hubにプッシュする条件分岐を書いてください。

jobs: push: if: github.ref == ‘refs/heads/main’ runs-on: ubuntu-latest steps: – name: Push to Docker Hub run: docker push myapp:latest

if:を使用して条件を指定できます。

📝 STEP 23 のまとめ

✅ このステップで学んだこと
  • CI/CD:継続的インテグレーション/デプロイの概念
  • GitHub Actions:YAMLでワークフロー定義
  • Docker Hub連携:自動イメージプッシュ
  • Trivy:コンテナの脆弱性スキャン
  • タグ戦略:ブランチ、バージョン、SHAベースのタグ
📊 ワークフロー要素 早見表
要素用途
on:トリガーpush, pull_request, schedule
jobs:ジョブ定義test, build, deploy
needs:依存関係needs: test
if:条件分岐if: github.ref == ‘refs/heads/main’
secrets.シークレット参照${{ secrets.TOKEN }}
🎯 次のステップの予告

次のSTEP 24では、「トラブルシューティングとベストプラクティス」を学びます。

  • よくあるエラーと対処法
  • セキュリティのベストプラクティス
  • リソース制限の設定
  • 次のステップ:Kubernetes入門
📝

学習メモ

Docker・コンテナ技術入門 - Step 23

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE