なぜテンプレ化するのか
個人開発で 3 つ目以降のプロジェクトを始めるとき、docker-compose.yml を 0 から書く時間 が一番無駄だ。前のプロジェクトをコピペしてくる、という名の儀式に毎回 30 分溶ける。
私は標準テンプレを 1 つ作って、新規プロジェクトはそれをコピーで始める運用に切り替えた。テンプレに含めるのは:
- backend (Rails API)
- frontend (Next.js)
- db (MySQL)
- redis (Sidekiq + cache)
これで開発環境は十分。本番は別に docker-compose.prod.yml を持つ。
開発環境テンプレ
# docker-compose.yml
services:
db:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: app_dev
TZ: Asia/Tokyo
ports: ['2306:3306']
volumes:
- db-data:/var/lib/mysql
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', '-proot']
interval: 5s
timeout: 3s
retries: 30
redis:
image: redis:8-alpine
ports: ['6379:6379']
volumes:
- redis-data:/data
backend:
build: ./backend
command: bin/rails server -b 0.0.0.0 -p 3000
environment:
DATABASE_URL: mysql2://root:root@db:3306/app_dev
REDIS_URL: redis://redis:6379/0
ports: ['2001:3000']
volumes:
- ./backend:/app
- bundle-cache:/usr/local/bundle
depends_on:
db: { condition: service_healthy }
redis: { condition: service_started }
frontend:
build: ./frontend
command: yarn dev -H 0.0.0.0 -p 3000
environment:
NEXT_PUBLIC_API_URL: http://localhost:2001/api/v1
NEXT_PUBLIC_SSR_API_URL: http://backend:3000/api/v1
ports: ['2000:3000']
volumes:
- ./frontend:/app
- frontend-modules:/app/node_modules
depends_on:
- backend
volumes:
db-data:
redis-data:
bundle-cache:
frontend-modules:
ポイント 5 つ
実運用で気付いた標準化観点:
1. ポートを 2000 番台に逃がす
3000 3306 は他プロジェクトと衝突しがち。フロントは 2000、API は 2001、DB は 2306 に逃がすと、複数プロジェクトを同時に立ち上げても干渉しない。
2. DB の healthcheck は必須
depends_on: { condition: service_healthy } を効かせるために mysqladmin ping の healthcheck を書く。これが無いと、make build 直後に backend が DB 接続エラーで死ぬ。
3. bundle / node_modules は named volume
ホストとマウントするとパフォーマンスが落ちるし、OS 間で互換性が壊れる。named volume に逃がす のが定石。
4. SSR / CSR 用の API URL 分岐
NEXT_PUBLIC_API_URL (ブラウザから) と NEXT_PUBLIC_SSR_API_URL (Next.js コンテナから) を 別途用意。前者は localhost:2001、後者は backend:3000。
5. TZ と locale を明示
TZ: Asia/Tokyo を DB と app コンテナ両方で設定。ログのタイムスタンプと Time.zone が日本時間で揃う。
Makefile も標準化
.PHONY: build up down rspec lint type_check pre_commit_check
build:
docker compose build
docker compose run --rm backend bin/rails db:create db:migrate
docker compose run --rm frontend yarn install
up:
docker compose up -d
down:
docker compose down
rspec:
docker compose exec backend bundle exec rspec
lint_fix:
docker compose exec backend bundle exec rubocop -A
docker compose exec frontend yarn lint:fix
type_check:
docker compose exec frontend yarn type-check
pre_commit_check: rspec lint_fix type_check
まとめ
テンプレは「コピーでスタートできる最小単位」を目指す。個別プロジェクトの特殊事情はオーバーライドで吸収する。
このテンプレで毎回 30 分の儀式が 0 になる。書き終えた直後の自己満足を超えて、3 プロジェクト目から本当に効く。
標準化は一度書けば永遠に効く投資。最初の 1 日に書く。