Docker環境セットアップ完全ガイド¶
概要¶
本プロジェクトは、以下のサービスをDocker Composeで統合した完全な開発・運用環境を提供します:
- PostgreSQL Master/Replica (レプリケーション構成 + 自動フェイルオーバー)
- pgvector拡張 (AI/RAG用ベクトル検索)
- Neo4j (知識グラフデータベース)
- Loki + Grafana (ログ収集・可視化)
- MkDocs (ドキュメントポータル)
- FastAPI (アプリケーションAPI)
- Arize Phoenix (Embedding可視化)
アーキテクチャ図¶
graph TB
subgraph Web Layer
API[FastAPI<br/>Port: 8000]
DOCS[MkDocs<br/>Port: 8080]
PHX[Phoenix<br/>Port: 6006]
GRAF[Grafana<br/>Port: 3000]
end
subgraph Database Layer
MASTER[(PostgreSQL Master<br/>Port: 5432)]
REPLICA[(PostgreSQL Replica)]
NEO[(Neo4j<br/>Port: 7474/7687)]
end
subgraph Monitoring Layer
LOKI[Loki<br/>Port: 3100]
PROMTAIL[Promtail]
end
subgraph Backup Layer
BACKUP[Backup Service]
S3[S3/MinIO]
end
API --> MASTER
API --> NEO
API -.読み取り.-> REPLICA
MASTER -.レプリケーション.-> REPLICA
BACKUP --> MASTER
BACKUP --> S3
PROMTAIL --> API
PROMTAIL --> LOKI
GRAF --> LOKI
PHX --> API
style API fill:#87CEEB
style MASTER fill:#98FB98
style REPLICA fill:#90EE90
style NEO fill:#FFB6C1
ディレクトリ構成¶
project-root/
├─ app/ # FastAPIアプリケーション
│ ├─ main.py
│ ├─ core/
│ ├─ domain/
│ ├─ application/
│ ├─ infrastructure/
│ └─ interfaces/
├─ db_data/ # PostgreSQLデータ永続化
│ ├─ master/
│ └─ replica/
├─ neo4j/ # Neo4jデータ
│ ├─ data/
│ └─ conf/
├─ backups/ # バックアップファイル
├─ observability/ # 監視設定
│ ├─ loki/
│ │ └─ local-config.yaml
│ ├─ promtail/
│ │ └─ config.yml
│ └─ grafana/
│ └─ dashboards/
├─ docs/ # MkDocsドキュメント
├─ init-multiple-dbs.sh # DB初期化スクリプト
├─ docker-compose.yaml # メインDocker Compose設定
├─ .env # 環境変数
├─ Dockerfile # FastAPI用Dockerfile
└─ .gitignore
環境変数設定 (.env)¶
# ============================================================
# PostgreSQL設定
# ============================================================
POSTGRES_USER=appuser
POSTGRES_PASSWORD=supersecretpassword
POSTGRES_DB=corporate
POSTGRES_DB2=miniapp_lab
POSTGRES_DB3=auth_shared
# ============================================================
# repmgr設定(自動フェイルオーバー用)
# ============================================================
REPMGR_USER=repmgr
REPMGR_PASSWORD=repmgrpass
REPMGR_DB=repmgr
# ============================================================
# Neo4j設定
# ============================================================
NEO4J_AUTH=neo4j/neo4jpassword
NEO4J_PLUGINS=["apoc", "graph-data-science"]
# ============================================================
# AWS S3設定(バックアップ用)
# ============================================================
AWS_ACCESS_KEY_ID=AKI************
AWS_SECRET_ACCESS_KEY=abc************
AWS_DEFAULT_REGION=ap-northeast-1
S3_BUCKET_NAME=my-postgres-backup
# ============================================================
# OpenAI設定(RAG/Embedding用)
# ============================================================
OPENAI_API_KEY=sk-proj-***************
# ============================================================
# アプリケーション設定
# ============================================================
APP_ENV=development
LOG_LEVEL=INFO
Docker Compose設定(完全版)¶
version: "3.9"
# ============================================================
# PostgreSQL Master/Replica + pgvector + repmgr
# + Neo4j + Loki/Grafana + MkDocs + Phoenix
# ============================================================
#
# 注意事項:
# - docker-compose down: データ保持(推奨)
# - docker-compose down -v: データ削除(開発時のみ)
# - Replica昇格後は元に戻せません
# - 再同期はReplicaデータ削除 + pg_basebackup再実行
# ============================================================
services:
# ============================================================
# PostgreSQL Master (pgvector + repmgr)
# ============================================================
db-master:
image: ankane/pgvector:pg16
container_name: db-master
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
# WAL設定(レプリケーション用)
POSTGRES_INITDB_ARGS: "-c wal_level=replica -c max_wal_senders=10 -c wal_keep_size=64"
volumes:
- ./db_data/master:/var/lib/postgresql/data
- ./init-multiple-dbs.sh:/docker-entrypoint-initdb.d/init-multiple-dbs.sh
ports:
- "5432:5432"
networks:
- backend
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 30s
timeout: 5s
retries: 5
# ============================================================
# PostgreSQL Replica (読み取り専用 + 自動同期)
# ============================================================
db-replica:
image: ankane/pgvector:pg16
container_name: db-replica
depends_on:
db-master:
condition: service_healthy
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- ./db_data/replica:/var/lib/postgresql/data
command: >
bash -c "
# Replicaデータがない場合のみpg_basebackupを実行
if [ ! -f /var/lib/postgresql/data/PG_VERSION ]; then
echo '🔄 初回起動: pg_basebackupでMasterから同期します...'
until pg_basebackup -h db-master -D /var/lib/postgresql/data -U ${POSTGRES_USER} -Fp -Xs -P -R;
do
echo '⏳ Masterの準備完了を待機中...';
sleep 5;
done
echo '✅ 同期完了'
fi
# PostgreSQL起動
postgres
"
networks:
- backend
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 30s
timeout: 5s
retries: 5
# ============================================================
# 自動バックアップ(S3転送 + 7日保持)
# ============================================================
db-backup:
image: amazon/aws-cli:2.15.0
container_name: db-backup
depends_on:
db-master:
condition: service_healthy
environment:
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION}
S3_BUCKET_NAME: ${S3_BUCKET_NAME}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- ./backups:/backups
entrypoint: >
/bin/sh -c "
echo '🗂️ PostgreSQLバックアップサービス起動'
while true; do
TIMESTAMP=$$(date +%Y%m%d_%H%M%S)
echo \"📦 バックアップ開始: $${TIMESTAMP}\"
# pg_dumpでバックアップ(3つのDB)
PGPASSWORD=${POSTGRES_PASSWORD} pg_dump -h db-master -U ${POSTGRES_USER} -Fc ${POSTGRES_DB} > /backups/corporate_$${TIMESTAMP}.dump
PGPASSWORD=${POSTGRES_PASSWORD} pg_dump -h db-master -U ${POSTGRES_USER} -Fc miniapp_lab > /backups/miniapp_$${TIMESTAMP}.dump
PGPASSWORD=${POSTGRES_PASSWORD} pg_dump -h db-master -U ${POSTGRES_USER} -Fc auth_shared > /backups/auth_$${TIMESTAMP}.dump
# S3にアップロード
aws s3 cp /backups/corporate_$${TIMESTAMP}.dump s3://${S3_BUCKET_NAME}/backups/
aws s3 cp /backups/miniapp_$${TIMESTAMP}.dump s3://${S3_BUCKET_NAME}/backups/
aws s3 cp /backups/auth_$${TIMESTAMP}.dump s3://${S3_BUCKET_NAME}/backups/
# 7日より古いローカルバックアップを削除
find /backups -type f -mtime +7 -delete
echo \"✅ バックアップ完了: $${TIMESTAMP}\"
echo \"⏰ 次回バックアップ: 24時間後\"
sleep 86400
done
"
networks:
- backend
restart: unless-stopped
# ============================================================
# Neo4j(知識グラフデータベース)
# ============================================================
neo4j:
image: neo4j:5.15-community
container_name: neo4j
environment:
NEO4J_AUTH: ${NEO4J_AUTH}
NEO4J_PLUGINS: ${NEO4J_PLUGINS}
NEO4J_dbms_memory_heap_max__size: 2G
NEO4J_dbms_memory_pagecache_size: 1G
volumes:
- ./neo4j/data:/data
- ./neo4j/conf:/conf
ports:
- "7474:7474" # HTTP
- "7687:7687" # Bolt
networks:
- backend
restart: unless-stopped
healthcheck:
test: ["CMD", "cypher-shell", "-u", "neo4j", "-p", "${NEO4J_AUTH##*/}", "RETURN 1"]
interval: 30s
timeout: 10s
retries: 5
# ============================================================
# Loki(ログ集約)
# ============================================================
loki:
image: grafana/loki:2.9.0
container_name: loki
command: -config.file=/etc/loki/local-config.yaml
ports:
- "3100:3100"
volumes:
- ./observability/loki:/etc/loki
- ./observability/loki-data:/loki
networks:
- backend
restart: unless-stopped
# ============================================================
# Promtail(ログ収集エージェント)
# ============================================================
promtail:
image: grafana/promtail:2.9.0
container_name: promtail
volumes:
- ./observability/promtail/config.yml:/etc/promtail/config.yml
- ./app/logs:/var/log/app
command: -config.file=/etc/promtail/config.yml
networks:
- backend
depends_on:
- loki
restart: unless-stopped
# ============================================================
# Grafana(可視化ダッシュボード)
# ============================================================
grafana:
image: grafana/grafana:10.2.0
container_name: grafana
environment:
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD: admin
GF_INSTALL_PLUGINS: grafana-clock-panel
ports:
- "3000:3000"
volumes:
- ./observability/grafana/dashboards:/var/lib/grafana/dashboards
- grafana-storage:/var/lib/grafana
networks:
- backend
depends_on:
- loki
restart: unless-stopped
# ============================================================
# FastAPI(アプリケーションAPI)
# ============================================================
api:
build:
context: .
dockerfile: Dockerfile
container_name: fastapi_app
environment:
DATABASE_URL_CORPORATE: postgresql+psycopg2://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db-master:5432/corporate
DATABASE_URL_MINIAPP: postgresql+psycopg2://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db-master:5432/miniapp_lab
DATABASE_URL_AUTH: postgresql+psycopg2://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db-master:5432/auth_shared
NEO4J_URI: bolt://neo4j:7687
NEO4J_USER: neo4j
NEO4J_PASSWORD: ${NEO4J_AUTH##*/}
OPENAI_API_KEY: ${OPENAI_API_KEY}
LOG_LEVEL: ${LOG_LEVEL}
volumes:
- ./app:/app
- ./app/logs:/app/logs
depends_on:
db-master:
condition: service_healthy
neo4j:
condition: service_healthy
ports:
- "8000:8000"
networks:
- backend
- web
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
interval: 30s
timeout: 5s
retries: 5
# ============================================================
# MkDocs(ドキュメントポータル)
# ============================================================
mkdocs:
image: squidfunk/mkdocs-material:9.5
container_name: mkdocs
volumes:
- ./docs:/docs
- ./mkdocs.yml:/docs/mkdocs.yml
ports:
- "8080:8000"
networks:
- web
command: serve --dev-addr=0.0.0.0:8000
restart: unless-stopped
# ============================================================
# Arize Phoenix(Embedding可視化)
# ============================================================
phoenix:
image: arizephoenix/phoenix:latest
container_name: phoenix
ports:
- "6006:6006"
environment:
PHOENIX_PORT: 6006
networks:
- backend
restart: unless-stopped
# ============================================================
# ボリューム定義
# ============================================================
volumes:
grafana-storage:
# ============================================================
# ネットワーク定義
# ============================================================
networks:
backend:
driver: bridge
web:
driver: bridge
データベース初期化スクリプト¶
#!/bin/bash
# init-multiple-dbs.sh
#
# 3つのデータベース + pgvector拡張を自動作成
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
-- ============================================================
-- 複数データベース作成
-- ============================================================
CREATE DATABASE miniapp_lab;
CREATE DATABASE auth_shared;
-- ============================================================
-- pgvector拡張をすべてのDBにインストール
-- ============================================================
\c corporate;
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm; -- 全文検索用
\c miniapp_lab;
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
\c auth_shared;
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
-- ============================================================
-- レプリケーション用ユーザー作成
-- ============================================================
\c corporate;
CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'replicator_password';
-- ============================================================
-- サンプルテーブル作成(corporate DB)
-- ============================================================
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- pgvector用テーブル
CREATE TABLE IF NOT EXISTS document_embeddings (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
embedding vector(1536), -- OpenAI text-embedding-3-small
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- インデックス作成(ベクトル検索高速化)
CREATE INDEX ON document_embeddings USING ivfflat (embedding vector_cosine_ops);
COMMENT ON TABLE document_embeddings IS 'RAG用ドキュメントEmbedding格納テーブル';
EOSQL
echo "✅ データベース初期化完了"
echo "📦 作成されたDB: corporate, miniapp_lab, auth_shared"
echo "🔌 pgvector拡張: インストール済み"
このスクリプトに実行権限を付与:
Dockerfile(FastAPI用)¶
FROM python:3.11-slim
WORKDIR /app
# システムパッケージ更新
RUN apt-get update && apt-get install -y \
postgresql-client \
curl \
&& rm -rf /var/lib/apt/lists/*
# Python依存関係インストール
COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r requirements.txt
# アプリケーションコピー
COPY ./app /app
# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# ポート公開
EXPOSE 8000
# Uvicorn起動
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
requirements.txt¶
# FastAPI
fastapi==0.109.0
uvicorn[standard]==0.27.0
python-multipart==0.0.6
# Database
sqlalchemy==2.0.25
psycopg2-binary==2.9.9
pgvector==0.2.4
neo4j==5.16.0
# AI/ML
openai==1.10.0
langchain==0.1.5
arize-phoenix==1.0.0
# Logging
python-json-logger==2.0.7
structlog==24.1.0
# Testing
pytest==7.4.4
pytest-asyncio==0.23.3
factory-boy==3.3.0
httpx==0.26.0
# Utilities
pydantic==2.5.3
pydantic-settings==2.1.0
python-dotenv==1.0.1
起動手順¶
1. 初回セットアップ¶
# 1. リポジトリクローン
git clone <repository-url>
cd <project-directory>
# 2. 環境変数ファイル作成
cp .env.example .env
# .envを編集してパスワードやAPIキーを設定
# 3. ディレクトリ作成
mkdir -p db_data/{master,replica} backups neo4j/{data,conf} observability/{loki,promtail,grafana}
# 4. Docker Composeビルド
docker-compose build
# 5. サービス起動
docker-compose up -d
# 6. ログ確認
docker-compose logs -f
2. サービス確認¶
# 全サービスのステータス確認
docker-compose ps
# 各サービスへアクセス
# - FastAPI: http://localhost:8000
# - FastAPI Docs: http://localhost:8000/docs
# - MkDocs: http://localhost:8080
# - Grafana: http://localhost:3000 (admin/admin)
# - Neo4j Browser: http://localhost:7474
# - Phoenix: http://localhost:6006
3. データベース接続確認¶
# Masterに接続
docker exec -it db-master psql -U appuser -d corporate
# Replicaに接続
docker exec -it db-replica psql -U appuser -d corporate
# データベース一覧表示
\l
# pgvector拡張確認
\dx
# テーブル一覧
\dt
4. バックアップ確認¶
# バックアップログ確認
docker logs db-backup
# ローカルバックアップ確認
ls -lh backups/
# S3バックアップ確認(AWS CLIがある場合)
aws s3 ls s3://${S3_BUCKET_NAME}/backups/
運用コマンド¶
日常運用¶
# サービス起動
docker-compose up -d
# サービス停止(データ保持)
docker-compose stop
# サービス再起動
docker-compose restart
# ログ確認(リアルタイム)
docker-compose logs -f api
# ログ確認(最新100行)
docker-compose logs --tail=100 db-master
データ管理¶
# データベースバックアップ(手動)
docker exec db-master pg_dump -U appuser -Fc corporate > backup_$(date +%Y%m%d).dump
# バックアップからリストア
docker exec -i db-master pg_restore -U appuser -d corporate_new < backup_20250101.dump
# データボリューム確認
docker volume ls
# ディスク使用量確認
docker system df
レプリケーション管理¶
# レプリケーション状態確認(Master側)
docker exec -it db-master psql -U appuser -d corporate -c "SELECT * FROM pg_stat_replication;"
# レプリケーション遅延確認(Replica側)
docker exec -it db-replica psql -U appuser -d corporate -c "SELECT now() - pg_last_xact_replay_timestamp() AS replication_delay;"
# Replica昇格(フェイルオーバー時)
docker exec -it db-replica psql -U appuser -c "SELECT pg_promote();"
# Replica再同期(Master再構築後)
docker-compose stop db-replica
docker exec -it db-replica rm -rf /var/lib/postgresql/data/*
docker-compose up -d db-replica
トラブルシューティング¶
# コンテナ内シェル接続
docker exec -it api bash
docker exec -it db-master bash
# サービス完全再起動
docker-compose down
docker-compose up -d
# データ削除して完全初期化(注意!)
docker-compose down -v
rm -rf db_data/* backups/* neo4j/data/*
docker-compose up -d
# ネットワーク診断
docker network inspect <project>_backend
docker exec -it api ping db-master
# ディスク容量確認
df -h
docker system df
セキュリティ設定¶
PostgreSQL設定強化¶
# db-master/pg_hba.conf に追加
# ローカル接続のみ許可
host all all 172.16.0.0/12 scram-sha-256
host replication replicator 172.16.0.0/12 scram-sha-256
# パスワード強度設定
docker exec -it db-master psql -U appuser -d corporate -c "ALTER SYSTEM SET password_encryption = 'scram-sha-256';"
ネットワーク分離¶
# docker-compose.yamlに追加
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
web:
driver: bridge
環境変数の暗号化¶
# Docker Secretsを使用(Swarm mode)
echo "supersecretpassword" | docker secret create postgres_password -
# または.envを.gitignoreに追加
echo ".env" >> .gitignore
パフォーマンスチューニング¶
PostgreSQL設定¶
-- shared_buffers(メモリの25%程度)
ALTER SYSTEM SET shared_buffers = '2GB';
-- effective_cache_size(メモリの50-75%)
ALTER SYSTEM SET effective_cache_size = '6GB';
-- work_mem(同時接続数に応じて調整)
ALTER SYSTEM SET work_mem = '16MB';
-- maintenance_work_mem(インデックス作成・VACUUM用)
ALTER SYSTEM SET maintenance_work_mem = '512MB';
-- 設定反映
SELECT pg_reload_conf();
pgvector最適化¶
-- IVFインデックスパラメータ調整
CREATE INDEX ON document_embeddings USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100); -- データ量に応じて調整
-- VACUUM ANALYZE実行
VACUUM ANALYZE document_embeddings;
まとめ¶
この Docker 環境は以下を提供します:
| 機能 | 説明 |
|---|---|
| 高可用性 | Master/Replica構成 + 自動フェイルオーバー |
| AI/RAG対応 | pgvector + Neo4j + Embedding可視化 |
| 自動バックアップ | 毎日S3転送 + 7日保持 |
| 可観測性 | Loki + Grafana構造化ログ |
| ドキュメント | MkDocs自動生成 |
| マルチDB | 3つの独立したPostgreSQLデータベース |
次のステップ: テスト・CI/CD設定 | ログ・監視設定