AetherEchoesEngineering
Vol.042026年5月9日
Engineering#00591 min5376 view

個人開発の docker-compose.yml をテンプレ化する

半年に 1 度作る Rails + Next.js + MySQL + Redis 構成を、テンプレ化してコピーで動く形に。本番 / 開発の差分は override で。

SoSoraEndo2026年5月9日1 min537

なぜテンプレ化するのか

個人開発で 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 日に書く。

Tags

Reaction

Share

X (Twitter)