Contents
DockerによるFlaskアプリケーションのデプロイ概要
FlaskアプリをDockerでデプロイすることで、開発環境と本番環境の不一致や依存関係の管理といった課題が解決されます。コンテナ化により、コード、ライブラリ、設定を一つの「箱」として扱うことで、誰でも同じ環境で動作させることが可能になります。特にマルチコンテナ構成(アプリケーション・データベース・ロードバランサー)は、高可用性とスケーラビリティを実現するための基本です。以下では、Dockerfile作成からAWSへのデプロイまでの一連の流れを解説します。
Dockerfileの作成方法とベストプラクティス
FlaskアプリをDockerで動作させるには、Dockerfileを作成し、必要な環境を定義する必要があります。ここでは基本的な構文とセキュリティ対策のポイントを解説します。
ベースイメージ選定のポイント
ベースイメージはプロジェクトの特性に応じて選びます。
- Python公式イメージ(例:
python:3.10-slim):Lightweightで信頼性が高く、多数のプロジェクトで採用されています。 - 特定のライブラリを含むカスタムイメージ:Docker Hubに公開されているカスタムイメージを使うことで、導入時間を短縮できます。
以下はベースイメージ選定時の比較表です:
|
1 2 3 4 5 6 |
| ベースイメージ | サイズ(MB) | 信頼性 | 推奨用途 | |---------------------|-------------|--------|------------------------| | `python:3.10-slim` | 45 | 高 | 新規プロジェクト | | `python:3.10-alpine` | 60 | 中 | リソース制限のある環境 | | `jupyter/base-notebook`| 1200 | 中 | Jupyter Notebook連携 | |
マルチステージビルドの活用法
マルチステージビルドは、ビルド環境とランタイム環境を分離することでイメージサイズを小さくする手法です。開発環境で必要なパッケージ(pip install)を一時的にインストールし、最終的にはそれらを排除して軽量なイメージを作成します。
以下が基本的なDockerfileの例です:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# ビルド用イメージ FROM python:3.10-slim AS builder WORKDIR /app COPY requirements.txt . RUN pip install --user -r requirements.txt # 実行環境用イメージ FROM python:3.10-slim WORKDIR /app COPY --from=builder /root/.local /root/.local ENV PATH=/root/.local/bin:$PATH COPY . . CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"] |
blockquote:
--userオプションは、インストールしたパッケージが非rootユーザーのホームディレクトリに保存されるようにするための指定です。これにより、ランタイム環境でのセキュリティ強化が可能です。
セキュリティ対策のポイント
- 非rootユーザー作成:
USER nonrootで実行時ユーザーを切り替えることで、攻撃時のリスクを抑える。 - 脆弱性スキャン:Docker Build時に
docker scanで自動チェックを行う。
blockquote: セキュリティ対策として、
pip install --userや非rootユーザーの導入は必須です。
Docker Composeによるマルチコンテナ環境構築
Docker Composeを使うことで、アプリケーション・データベース・ロードバランサーを一つのファイルで定義できます。以下に基本的なサービス定義と依存関係管理のコツを解説します。
サービス定義ファイルの基本構造
docker-compose.ymlはYAML形式で記述され、サービスごとの設定を定義します。以下がシンプルな例です:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
version: '3.8' services: app: build: . ports: - "5000:5000" environment: FLASK_ENV: production env_file: - .env depends_on: - db - redis db: image: postgres:14 volumes: - db_data:/var/lib/postgresql/data environment: POSTGRES_USER: user POSTGRES_PASSWORD: password redis: image: redis:6.2 ports: - "6379:6379" volumes: db_data: |
この設定では、appサービスが.envファイルから環境変数を読み込み、dbとredisに依存しており、起動順序を自動で管理します。
依存関係管理のコツ
- ネットワーク構成:
depends_onで依存関係を明示し、サービス間通信を確実に。 - ボリュームマウント:データ永続化が必要な場合は、
volumesでホストとコンテナを同期させる。
blockquote:
docker-compose up --buildで一括起動し、docker-compose downで停止・削除できます。
NginxとWSGIサーバー(Gunicorn/uWSGI)の統合構成
FlaskアプリケーションはNginxとWSGIサーバーを組み合わせてスケーラブルに構築することが可能です。ロードバランシングや静的ファイル配信の最適化を解説します。
ロードバランシング設定の基本
Nginxをリバースプロキシーとして配置し、複数のWSGIサーバー(Gunicorn)にリクエストを分散させます。以下の例ではポート80と443への接続を定義しています:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
server { listen 80; server_name myapp.example.com; location / { proxy_pass http://flask_app; include proxy_params; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } upstream flask_app { server app1:5000 weight=3; server app2:5000 weight=1; } |
静的ファイル配信の最適化
Nginxは静的ファイル(CSS/JS)を直接配信できるため、WSGIサーバーの負荷を軽減します。以下が設定例です:
|
1 2 3 4 5 |
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public, no-transform"; } |
blockquote: 静的ファイル配信はNginxに任せるのが効率的で、パフォーマンス向上につながります。
AWSへのデプロイ手順と自動化戦略
AWSではEC2インスタンスやECSクラスターを使ってDockerコンテナをスケールさせます。ここでは手動構築と自動化の具体例を解説します。
EC2インスタンスでの手動構築
- AMI作成:デプロイ対象となるDockerイメージを含むAMIを作成し、AWSにアップロードします。
- インスタンス起動:AMIからEC2インスタンスを起動し、セキュリティグループでポート5000や80を開けます。
- Dockerデーモン設定:
/etc/docker/daemon.jsonにリソース制限やログ出力の設定を追加します。
ECSでコンテナをスケールさせる方法
ECSクラスターでは、タスク定義とサービスを作成することで自動スケーリングが可能です。以下が手順です:
- タスク定義作成:Dockerイメージのバージョンやリソース制限(CPU/Memory)を指定。
- サービス構築:タスクが常に起動するように設定し、デプロイ時に自動更新されます。
blockquote: Infrastructure as Code(Terraform/CloudFormation)を使うことで、環境構成のバージョン管理が容易になります。
環境変数管理とセキュリティ強化策
本番環境ではセキュリティリスクを抑えるため、環境変数を適切に管理することが重要です。.envファイルやSecrets Managerとの連携方法を解説します。
.envファイルのベストプラクティス
Docker Composeでは.envファイルで環境変数を定義できます。以下が例です:
|
1 2 3 4 |
FLASK_ENV=production SECRET_KEY=my_super_secure_key DATABASE_URL=postgres://user:password@db:5432/mydb |
このファイルは.gitignoreに記載し、公開しないようにします。
Secrets Managerとの連携方法
AWS Secrets Managerには以下のようにアクセスできます:
- Secretsの作成:APIキーやパスワードをSecrets Managerに保存。
- Lambda関数での取得:コンテナ起動時にLambda経由でシークレットを取得し、環境変数として使用します。
|
1 2 3 4 5 6 7 8 9 10 |
import boto3 def lambda_handler(event, context): client = boto3.client('secretsmanager', region_name='us-west-2') secret_value = client.get_secret_value(SecretId='my-secret-name')['SecretString'] return { 'statusCode': 200, 'body': secret_value } |
blockquote: シークレットはコードに埋め込まないことがセキュリティの基本です。
まとめ
DockerによるFlaskアプリケーションのデプロイには、以下が重要です。
- Dockerfileとマルチステージビルドで軽量なイメージを作成
- Docker Composeで複数サービスを統一管理
- Nginx + Gunicornによる高性能なWeb構成
- AWS EC2/ECSでのスケーラブルなデプロイ
- .envとSecrets Managerによるセキュアな環境変数管理
これらの手順を踏むことで、Flaskアプリケーションを本番環境で安定して動作させることができます。今すぐDockerでFlaskアプリをデプロイしてみましょう!