version: '3.8'
services:
postgres:
image: postgres:16-alpine
container_name: app_postgres
restart: unless-stopped
environment:
POSTGRES_USER: devuser
POSTGRES_PASSWORD: devpassword
POSTGRES_DB: app_dev
ports:
- "5432:5432"
volumes:
- postgres_data:/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
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:Mi-am pierdut jumătate de zi acum o lună configurând mediul local pentru un coleg nou. Ba avea Node v18 în loc de v20, ba Postgres-ul local rula pe alt port, ba uita să pornească Redis și se plângea că-i crapă sesiunile. Am tăiat timpul de onboarding de la 2 ore la sub 3 minute cu o singură comandă: docker compose up -d.
Filozofia: ce băgăm în Docker și ce lăsăm pe host?
Am văzut multe echipe care încearcă să bage absolut totul în Docker, inclusiv scriptul de dev pentru Next.js. Funcționează impecabil pe hârtie, dar în practică vine cu un cost uriaș de performanță, mai ales dacă lucrezi pe macOS sau Windows unde I/O-ul pe volumele montate este dureros de lent. Hot-reload-ul ajunge să aibă un lag scârbos de 2-3 secunde la fiecare salvare, iar ventilatorul de la laptop sună ca o decolare de avion.
Trade-off-ul ideal pe care îl folosesc la un proiect cu 15k query-uri pe minut în producție și vreo 6 dev-i pe el e simplu:
- Serviciile de stocare și infrastructură (Postgres, Redis) le rulăm izolate în Docker.
- Aplicația Next.js o rulăm nativ pe host (
npm run dev), conectată prin.env.localla porturile expuse de containere.
În felul ăsta obții viteza maximă de compilare oferită de Turbopack pe host și flexibilitatea de a curăța baza de date în două secunde fără să-ți murdărești sistemul de operare cu instanțe locale de Postgres.
Configurația curată și capcanele de care m-am lovit
În fișierul docker-compose.yml pe care îl folosesc în aproape toate proiectele noi, există două chestii esențiale: healthcheck-ul pe baza de date și volumele denumite explicit.
Fără un healthcheck configurat corect, dacă ai un script de startup care rulează migrări de Prisma sau Drizzle la pornire, o să-ți crapă aleatoriu. Postgres raportează că e pregătit să primească conexiuni înainte să fi terminat de inițializat fișierele pe disc. De aceea pun un pg_isready sănătos care verifică starea reală.
Un alt detaliu practic: persistarea datelor. Dacă uiți să pui volume explicite pentru Postgres și Redis, de fiecare dată când dai un docker compose down sau îți repornești laptopul, îți pierzi toate datele de test. Am economisit ore întregi de muncă colegilor doar explicându-le de ce nu trebuie să stocheze fișierele bazei de date în containerul volatil.
Cum arată fluxul zilnic de lucru
Comenzile pe care le rulează oricine din echipă dimineața când își deschide laptopul sunt extrem de simple:
docker compose up -d— pornește stiva în fundal în mai puțin de două secunde.npm run dev— pornește serverul de Next.js pe host.
Când am terminat ziua de muncă, dau un simplu docker compose stop. Asta eliberează instant cei 350-400MB de RAM pe care îi consumă instanțele izolate. Fără servicii rămase agățate prin fundal, fără procese zombie și fără daemoni de bază de date care să mănânce resurse când vreau să mă joc ceva seara.
Voi cum abordați dev-ul local? Rulați și aplicația Node în container sau mergeți pe varianta hibridă?