services:
postgres:
image: postgres:16-alpine
container_name: app_postgres
restart: unless-stopped
environment:
POSTGRES_USER: devuser
POSTGRES_PASSWORD: devpass
POSTGRES_DB: app_dev
ports:
- "127.0.0.1:5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U devuser -d app_dev"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: app_redis
restart: unless-stopped
command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru
ports:
- "127.0.0.1:6379:6379"
volumes:
- redisdata:/data
volumes:
pgdata:
redisdata:Dacă instalezi Postgres și Redis direct pe sistemul de operare la fiecare proiect nou, în 6 luni ai 4 versiuni diferite de DB care se bat pe aceleași porturi. Îți las mai jos rețeta minimalistă de Docker Compose pe care o folosesc pe aproape orice proiect nou de Next.js ca să am totul sus în sub 10 secunde.
Decizia importantă: Node pe host vs. Node în Docker
Cea mai mare greșeală pe care o văd la juniori când încep cu Docker este că bagă și serverul de dev Next.js în container. Pare curat pe hârtie, dar în practică e frustrant.
La un proiect mediu cu vreo 12k fișiere și componente React, bind mount-ul de Docker pe macOS sau Windows (WSL2 configurat greșit) ne-a adus o latență de aproape 4 secunde la Fast Refresh. Cum am trecut pnpm dev direct pe mașina locală și am lăsat doar dependințele grele (Postgres, Redis) în Docker, timpul de reload a scăzut sub 200ms.
Trade-off-ul e simplu: pierzi 100% paritate cu mediul de producție pe partea de runtime Node, dar câștigi o viteză de dezvoltare masivă. Pentru dev local, eu aleg viteza în 9 cazuri din 10.
Cum arată fișierul de bază
Fișierul de mai jos e gândit să fie trântit în rădăcina proiectului. Are trei detalii esențiale pe care mulți le omit:
- Legarea porturilor pe
127.0.0.1: Nu expune5432:5432, ci127.0.0.1:5432:5432. Altfel, dacă ești pe un Wi-Fi public la cafenea, oricine din rețea poate încerca să-ți acceseze baza de dev dacă n-ai firewall agresiv. - Healthcheck real pe Postgres:
pg_isreadygarantează că baza chiar primește conexiuni, nu doar că a pornit procesul principal. - Volume denumite: Datele supraviețuiesc comenzilor de
docker compose down, dar pot fi șterse ușor cudocker compose down -vcând vrei un seed curat.
Conectarea din Next.js
În fișierul .env.local din Next.js, conexiunile devin extrem de directe pentru că DB-ul răspunde pe localhost-ul mașinii tale:
DATABASE_URL="postgresql://devuser:devpass@localhost:5432/app_dev?schema=public"
REDIS_URL="redis://localhost:6379"
Dacă la un moment dat vrei să rulezi migrările Prisma sau Drizzle, rulezi comanda nativ din terminalul tău (pnpm db:push). Nu mai e nevoie să intri cu docker exec în containere pentru fiecare migrare mică.
Pentru Redis, am pus maxmemory 128mb și policy de allkeys-lru. Nu ai nevoie de mai mult pentru cache local de sesiuni sau rate limiting în teste, și eviți situația în care Redis papă 1GB de RAM în fundal dacă uiți de el deschis două săptămâni.
Voi cum abordați dev-ul local: țineți și aplicația Next.js tot în container cu dev-watch sau preferați să rulați Node direct pe host?