デプロイとCI/CD
約10分
デプロイ(Deploy)とは、開発したアプリケーションを本番環境で動作させるプロセスです。「自分のMacでは動くのに本番で動かない」という問題はコンテナで解決できます。CI/CD(Continuous Integration / Continuous Deployment)とは、コードの変更を自動でテスト・ビルド・デプロイするパイプラインです。CI/CDを整備すると、手作業によるデプロイミスを排除し、1日何度でも安全にリリースできるようになります。
なぜデプロイプロセスを整備するのか
Section titled “なぜデプロイプロセスを整備するのか”手作業によるデプロイには次の問題があります。
- 開発環境と本番環境の差異(OS・ライブラリバージョン)による動作不一致
- 手順書のミスや手順の属人化
- デプロイのたびにサービス停止が発生する
- どのバージョンが本番で動いているか追跡できない
コンテナとCI/CDはこれらをまとめて解決します。
コンテナ(Docker)とは
Section titled “コンテナ(Docker)とは”コンテナとは、アプリケーションとその依存関係(ライブラリ、ランタイム、設定ファイル)をひとまとめにした隔離された実行環境です。コンテナは「どのサーバーでも同じように動く」を保証します。
Docker はコンテナを作成・実行する最も広く使われるツールです。
VMとコンテナの違い
Section titled “VMとコンテナの違い”| 比較項目 | 仮想マシン(VM) | コンテナ |
|---|---|---|
| 起動時間 | 数分 | 数秒 |
| サイズ | 数GB(OS込み) | 数十〜数百MB |
| リソース効率 | 低(OS全体を実行) | 高(ホストOSのカーネルを共有) |
| 隔離レベル | 強(完全なOS分離) | 中(プロセスレベルの分離) |
| 移植性 | 低(VMイメージは重い) | 高(コンテナイメージはどこでも動く) |
Dockerfile の基礎
Section titled “Dockerfile の基礎”Dockerfile とは、コンテナイメージの作成手順を記述するテキストファイルです。
# Python FastAPI アプリの Dockerfile 例
FROM python:3.12-slim # ベースイメージ(Python 3.12 の軽量版)
WORKDIR /app # コンテナ内の作業ディレクトリ
COPY requirements.txt . # 依存関係ファイルをコピー
RUN pip install --no-cache-dir -r requirements.txt # ライブラリをインストール
COPY . . # アプリのソースコードをコピー
EXPOSE 8000 # コンテナが公開するポート番号
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]# イメージをビルド
docker build -t my-ai-app:latest .
# コンテナを起動(ローカル確認用)
docker run -p 8000:8000 --env-file .env my-ai-app:latestコンテナレジストリ
Section titled “コンテナレジストリ”コンテナレジストリとは、Dockerイメージを保存・配布するサービスです。GitHubがコードを管理するように、レジストリはコンテナイメージを管理します。
| レジストリ | 特徴 |
|---|---|
| Docker Hub | 最も有名。パブリックイメージが豊富 |
| Amazon ECR | AWSとの統合が容易。ECS/EKSとセットで使う |
| GitHub Container Registry | GitHub Actionsとの連携が簡単 |
| Google Artifact Registry | GCP環境に統合 |
CI/CDパイプライン
Section titled “CI/CDパイプライン”CI(継続的インテグレーション)とCD(継続的デプロイ)
Section titled “CI(継続的インテグレーション)とCD(継続的デプロイ)”- CI(Continuous Integration): コードをプッシュするたびに自動でリント・テスト・ビルドを実行
- CD(Continuous Deployment): テストが通ったコードを自動でステージング・本番環境にデプロイ
GitHub Actions によるCI/CDパイプライン
Section titled “GitHub Actions によるCI/CDパイプライン”graph LR
Push["開発者がプッシュ\n(feature → main)"] --> CI["GitHub Actions\nCI ジョブ"]
CI --> Lint["① Lint チェック\n(flake8 / eslint)"]
Lint --> Test["② テスト実行\n(pytest / jest)"]
Test --> Build["③ Docker イメージ\nビルド"]
Build --> Push2["④ レジストリに\nイメージプッシュ"]
Push2 --> DeployStaging["⑤ ステージング環境\nへデプロイ"]
DeployStaging --> SmokeTest["⑥ スモークテスト\n(基本動作確認)"]
SmokeTest -->|合格| DeployProd["⑦ 本番環境\nへデプロイ"]
SmokeTest -->|不合格| Rollback["自動ロールバック"]
DeployProd --> Notify["⑧ Slack通知\n(デプロイ完了)"]GitHub Actions ワークフロー例
Section titled “GitHub Actions ワークフロー例”# .github/workflows/deploy.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run linter
run: flake8 src/
- name: Run tests
run: pytest tests/ -v
env:
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
build-and-deploy:
needs: test # testジョブが成功した場合のみ実行
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' # mainブランチへのpushのみ
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push Docker image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/my-ai-app:$IMAGE_TAG .
docker push $ECR_REGISTRY/my-ai-app:$IMAGE_TAG
- name: Deploy to ECS
run: |
aws ecs update-service \
--cluster production \
--service ai-chat-service \
--force-new-deploymentデプロイ環境
Section titled “デプロイ環境”本番AIサービスは通常3つの環境を用意します。
development(開発環境)
↓ プルリクエスト作成
staging(ステージング環境)
↓ mainへのマージ後、動作確認
production(本番環境)| 環境 | 目的 | インフラ規模 |
|---|---|---|
| development | 開発者のローカルまたは個人の開発サーバー | 最小 |
| staging | 本番に近い構成での動作確認 | 本番の縮小版 |
| production | 実際のユーザーが使う環境 | フルスケール |
デプロイ戦略
Section titled “デプロイ戦略”サービス停止を最小化しながらデプロイするための戦略が3つあります。
| 戦略 | 仕組み | 停止時間 | ロールバック速度 | 複雑さ |
|---|---|---|---|---|
| ローリングアップデート | 旧インスタンスを1台ずつ新バージョンに入れ替え | なし | 中 | 低 |
| ブルーグリーン | 旧環境(Blue)を残したまま新環境(Green)を用意し、トラフィックを一括切り替え | なし | 速い(即切り戻し可) | 中 |
| カナリアリリース | トラフィックの一部(例: 5%)だけ新バージョンに流し、問題なければ段階的に拡大 | なし | 速い | 高 |
ブルーグリーンデプロイのイメージ
Section titled “ブルーグリーンデプロイのイメージ”デプロイ前:
トラフィック 100% → [Blue環境: v1.2]
デプロイ中:
[Green環境: v1.3] を起動してテスト
トラフィック 100% → [Blue環境: v1.2]
切り替え後:
トラフィック 100% → [Green環境: v1.3]
[Blue環境: v1.2] は一定期間保持(ロールバック用)コンテナオーケストレーション: Kubernetes
Section titled “コンテナオーケストレーション: Kubernetes”Kubernetes(K8s)とは、大量のコンテナを自動で管理・スケールするオーケストレーションシステムです。「コンテナが落ちたら自動で再起動」「負荷が増えたら自動でスケールアウト」といった運用を自動化します。
Kubernetesの主要概念:
| 概念 | 役割 |
|---|---|
| Pod | 1つ以上のコンテナをまとめた最小デプロイ単位 |
| Deployment | Podの望ましい状態(レプリカ数等)を定義 |
| Service | Podへのネットワークアクセスを提供するロードバランサー |
| Ingress | 外部からのHTTPSトラフィックをServiceにルーティング |
| ConfigMap / Secret | 設定値・シークレットを管理 |
Kubernetesは強力ですが複雑です。小〜中規模のAIサービスではまずマネージドサービス(Cloud Run、Fargate、Railway)から始めることを推奨します。
クラウドデプロイ先の選択
Section titled “クラウドデプロイ先の選択”| サービス | 特徴 | 向くケース |
|---|---|---|
| AWS ECS / Fargate | サーバーレスコンテナ実行。Kubernetesより簡単 | AWSで本番運用 |
| Google Cloud Run | HTTPリクエストに応じて自動スケール | GCPでステートレスAPI |
| Railway | Dockerfileがあれば数分でデプロイ可能 | 個人・スタートアップ |
| Render | GitHubと連携した簡単デプロイ | 個人・スタートアップ |
| Heroku | 最も手軽なPaaS | 小規模 / プロトタイプ |
| Kubernetes(EKS/GKE) | 大規模・複雑な要件 | 大規模本番 |
環境変数とシークレット管理
Section titled “環境変数とシークレット管理”APIキーやDBパスワードをソースコードに直接書いてはいけません。
# ローカル開発: .env ファイルに記述し、.gitignore に追加
ANTHROPIC_API_KEY=sk-ant-xxxxx
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
REDIS_URL=redis://localhost:6379
# .gitignore
.env本番環境では、.env ファイルをサーバーに置く代わりに専用のシークレット管理サービスを使います。
| サービス | 説明 |
|---|---|
| AWS Secrets Manager | シークレットをローテーション含めて管理 |
| AWS SSM Parameter Store | シンプルなキーバリュー形式のシークレット |
| Google Secret Manager | GCPのシークレット管理 |
| GitHub Actions Secrets | CIパイプライン内でのみ使うシークレット |
| Vault (HashiCorp) | クラウド非依存のOSSシークレット管理 |
- コンテナ(Docker)は「どの環境でも同じように動く」を保証し、「自分のMacでは動く」問題を解決する
- Dockerfile でアプリと依存関係をパッケージ化し、コンテナレジストリで配布する
- GitHub ActionsでCI/CDを構築し、テスト→ビルド→デプロイを自動化する
- ローリング・ブルーグリーン・カナリアの3戦略でダウンタイムなしのデプロイが可能
- Kubernetesは本格的なコンテナオーケストレーションだが、まずCloud Run / Fargate / Railwayで始めるのが現実的
- シークレットはソースコードに入れず、必ずシークレット管理サービスを使う
よくある質問
Section titled “よくある質問”Q: Kubernetesは必要ですか?
A: 多くの場合、最初は不要です。AWS ECS/Fargate、Google Cloud Run、Railway などのマネージドサービスで自動スケーリングや自動再起動は実現できます。Kubernetesが必要になるのは、カスタムスケーリングロジック、複雑なネットワーク設定、大規模な本番運用が必要になったときです。
Q: デプロイが失敗したときにロールバックするには?
A: ブルーグリーンデプロイなら旧環境へのトラフィックを即時切り戻すだけです。ローリングアップデートの場合は、前のコンテナイメージタグを指定して再デプロイします。GitHub Actionsワークフローに「前のSHAに戻す」ジョブを用意しておくか、ECS/Cloud Runのコンソールから前のリビジョンに切り戻せます。
Q: ステージング環境は必ず必要ですか?
A: 本番ユーザーがいるサービスでは強く推奨します。ステージングなしで本番に直接デプロイすると、動作確認の機会がなく障害発生時の影響範囲が大きくなります。費用を抑えるなら、ステージングはより小さなインスタンスサイズにして最低限の構成にすることで十分です。
Q: GitHub Actions 以外のCI/CDツールはありますか?
A: GitLab CI/CD(GitLab利用者向け)、CircleCI(歴史あるクラウドCI)、Jenkins(OSS・オンプレでの細かい制御)などがあります。GitHubを使っているなら GitHub Actions が最も統合が簡単で、パブリックリポジトリなら無料枠があります。
このページの外部仕様・背景情報は、参考文献を参照してください。[1][2][3][4][5]