6.6 Docker Compose実践|Webアプリ+DB+リバースプロキシの本番構成を作る

Docker Compose

Docker Compose実践|Webアプリ+DB+リバースプロキシの本番構成を作る

第6章のクロージング。6-1〜6-5 で学んだ要素を全部乗せした実戦構成を組みます。題材は「ブラウザ → nginx → FastAPI → PostgreSQL」の典型3層。

💡 この記事のゴール
① 3層構成(proxy / app / db)を1つの compose.yml で一気に立ち上げる
② 学んだ全要素を統合:services / networks / volumes / depends_on + healthcheck / .env
docker compose up -d 一発でブラウザから叩ける状態に

目次

  1. 構成図
  2. ディレクトリ構成
  3. .env を作る
  4. アプリのコード(FastAPI最小)
  5. アプリのDockerfile
  6. nginx設定
  7. compose.yml 完成形
  8. 起動してブラウザ確認
  9. 日常操作
  10. まとめ

1. 構成図

【3層アーキテクチャ】
🌐 frontend-net(インターネット公開側)
🚪 proxy (nginx)
:80 公開

🐍 app (FastAPI)
:8000 内部

🔒 backend-net(DBアクセス専用)
🐍 app

🐘 db (PostgreSQL)
+ pgdata volume

↑ proxy から db は直接見えない(app を経由するしか入れない)多層防御

2. ディレクトリ構成

myapp/
├── compose.yml
├── .env                        ← DB_PASSWORD など
├── .env.example                ← Gitに入れる雛形
├── .gitignore                  ← .env を除外
├── nginx/
│   └── default.conf
└── app/
    ├── Dockerfile
    ├── main.py
    └── requirements.txt

3. .env を作る

# .env
DB_PASSWORD=s3cret_change_me
APP_PORT=80
# .env.example(Git コミットするひな形)
DB_PASSWORD=put-your-password-here
APP_PORT=80
# .gitignore
.env

4. アプリのコード(FastAPI最小)

# app/main.py
import os
import psycopg
from fastapi import FastAPI

app = FastAPI()
DATABASE_URL = os.environ["DATABASE_URL"]

@app.get("/")
def root():
    return {"message": "Hello from FastAPI 🎉"}

@app.get("/health")
def health():
    return {"status": "ok"}

@app.get("/dbcheck")
def dbcheck():
    with psycopg.connect(DATABASE_URL) as conn:
        with conn.cursor() as cur:
            cur.execute("SELECT version();")
            version = cur.fetchone()[0]
    return {"postgres": version}
# app/requirements.txt
fastapi==0.115.0
uvicorn[standard]==0.32.0
psycopg[binary]==3.2.3

5. アプリのDockerfile

# app/Dockerfile
FROM python:3.12-slim

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"]

6. nginx設定(リバースプロキシ)

# nginx/default.conf
server {
    listen 80;

    location / {
        proxy_pass http://app:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

ここでの http://app:8000 の「app」は、Compose が自動で名前解決するサービス名(5-1/5-2 で学んだ仕組み)。


7. compose.yml 完成形

# compose.yml
services:
  proxy:
    image: nginx:1.27
    ports:
      - "${APP_PORT}:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - app
    networks:
      - frontend-net
    restart: unless-stopped

  app:
    build: ./app
    environment:
      DATABASE_URL: postgres://postgres:${DB_PASSWORD}@db:5432/postgres
    depends_on:
      db:
        condition: service_healthy
    networks:
      - frontend-net
      - backend-net
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 10s

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - backend-net
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 10
      start_period: 10s

volumes:
  pgdata:

networks:
  frontend-net:
  backend-net:
ここに使っている機能 学んだ場所
${VAR} 展開 6-5 .env
build: 6-2 compose.yml
depends_on.condition: service_healthy 6-4 depends_on
healthcheck: 6-4 healthcheck
複数 networks: 5-2・6-2
Named Volume 4-2 / 6-2
ホストBind Mount(nginx設定) 4-3
restart: unless-stopped 2-5

8. 起動してブラウザ確認

# 構成検証
docker compose config -q

# 一括起動(ビルドも)
docker compose up -d --build

# 状態確認
docker compose ps
# proxy: Up ... 0.0.0.0:80->80/tcp
# app:   Up ... (healthy)
# db:    Up ... (healthy)

ブラウザで http://localhost/ を開くと:



🔒 http://localhost/

{“message”:”Hello from FastAPI 🎉”}

/dbcheck にアクセスすると PostgreSQL のバージョン文字列が返ります:



🔒 http://localhost/dbcheck

{“postgres”:”PostgreSQL 16.4 (Debian) on x86_64-pc-linux-gnu, compiled by gcc”}

✅ 通信経路
ブラウザ → nginx(:80) → frontend-net 経由で app:8000backend-net 経由で db:5432 → PostgreSQL が version を返す → app が JSON にして返す → nginx がクライアントへ返す。第5章・第6章で学んだすべてが1つの経路に結実しました。

9. 日常操作

# コード変更後の再デプロイ
docker compose up -d --build app

# アプリのログを追跡
docker compose logs -f app

# DB に psql で入る
docker compose exec db psql -U postgres

# 単発マイグレーション
docker compose run --rm app python -c "print('migrate here')"

# 完全停止
docker compose down

# 完全リセット(DBデータも消える!)
docker compose down -v

10. まとめ

第6章をクリアしたあなたは、以下ができるようになりました:

できるようになったこと
複数コンテナ構成を YAML 1枚で宣言
frontend/backend の2段ネットワーク分離
Named Volume による DB の永続化
Bind Mount による設定ファイル注入
healthcheck + depends_on で起動順を安全に制御
.env によるシークレット・パラメータの分離
docker compose up -d 一発で全員が同じ環境
✅ 第6章完了!次のステップ
ここまで「公式イメージ + Compose」で複雑な構成を組めるようになりました。次の第7章 レジストリとイメージ管理では、自分で作ったイメージを Docker Hub や プライベートレジストリに公開・配布する方法と、バージョン管理(タグ戦略)を扱います。チーム開発・CI/CDの基盤になる章です。

参考リンク


Dockerの基礎を動画で体系的に学びませんか?

実務で使う基礎だけを3時間に凝縮。環境構築から丁寧に解説しています。

Udemy Docker入門講座 クーポン割引で講座を見る →

コメント

タイトルとURLをコピーしました