Technical
Docker Compose for Local Development
Every project I work on has a database, sometimes a cache, sometimes a message queue. Running those locally used to mean installing Postgres on my laptop, remembering to start it, and dealing with version mismatches across projects. Docker Compose replaces all of that with one file per project.
The Single File
A docker-compose.yml at the project root describes every service the project needs to run locally:
version: '3.9'
services:
db:
image: postgres:16
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
POSTGRES_DB: app
ports:
- '5432:5432'
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7
ports:
- '6379:6379'
volumes:
pgdata:One command, docker compose up, and both services are running. One command, docker compose down, and they stop. The services disappear cleanly when I am done.
Why This Matters
Every new developer on the team clones the repo, runs one command, and has a working local environment. No 'install Postgres 14, not 15, then create this user, then set this config flag' onboarding document.
Onboarding time went from a morning to ten minutes for every project I use Docker Compose on.
Data Persistence
The volumes: section persists data between restarts. Stop the database, start it again, data is still there. Delete the volume (docker compose down -v) and you get a fresh database. That reset is useful when testing migrations from scratch.
Connecting the App
My app runs outside Docker (I do not containerize my own code during development). It connects to the containerized services via localhost:
DATABASE_URL=postgresql://dev:dev@localhost:5432/app
REDIS_URL=redis://localhost:6379That setup gives me live reloading from my IDE plus stable service dependencies. Best of both worlds.
When to Containerize the App Too
If the team includes Windows and macOS developers and you are seeing 'works on my machine' bugs, containerize the app. The overhead is worth the consistency. For solo or macOS-only teams, I skip it.
Production Is Different
Docker Compose is for development. In production I use managed services (RDS for Postgres, ElastiCache for Redis). The Compose file is not meant to deploy. It is meant to give developers a working environment.
The Portability Win
When I switch machines, I clone my repos and run docker compose up in each. Fifteen minutes later, I am productive. No installing databases on the new machine. The environment travels with the code.
See the Docker Compose documentation for the full spec and the official Postgres image docs for configuration options.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read