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
③
① 3層構成(proxy / app / db)を1つの compose.yml で一気に立ち上げる
② 学んだ全要素を統合:services / networks / volumes / depends_on + healthcheck / .env
③
docker compose up -d 一発でブラウザから叩ける状態に
目次
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/ を開くと:
/dbcheck にアクセスすると PostgreSQL のバージョン文字列が返ります:
✅ 通信経路
ブラウザ → nginx(:80) → frontend-net 経由で app:8000 → backend-net 経由で db:5432 → PostgreSQL が version を返す → app が JSON にして返す → nginx がクライアントへ返す。第5章・第6章で学んだすべてが1つの経路に結実しました。
ブラウザ → nginx(:80) → frontend-net 経由で app:8000 → backend-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の基盤になる章です。
ここまで「公式イメージ + Compose」で複雑な構成を組めるようになりました。次の第7章 レジストリとイメージ管理では、自分で作ったイメージを Docker Hub や プライベートレジストリに公開・配布する方法と、バージョン管理(タグ戦略)を扱います。チーム開発・CI/CDの基盤になる章です。
参考リンク
- Compose(公式) — 本章全体の一次情報源。
- FastAPI 公式 — サンプルで使ったWebフレームワーク。
- Docker Hub: postgres — 環境変数・初期化スクリプト配置の公式仕様。



コメント