infra
beginner

Docker Compose Dev

Architecture Visual

graph TD classDef actor fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#000 classDef gateway fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#000 classDef network fill:#f0f9ff,stroke:#0ea5e9,stroke-width:1px,stroke-dasharray: 5 5,color:#000 classDef service fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#000 classDef database fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#000 classDef function fill:#f3e8ff,stroke:#9333ea,stroke-width:2px,color:#000 subgraph app_containers ["Application Containers"] direction TB nginx["Nginx"]:::gateway frontend["Frontend Container"]:::service backend["Backend Container"]:::service worker["Worker Container"]:::service end subgraph data_containers ["Data Containers"] direction TB postgres["PostgreSQL"]:::database redis["Redis"]:::database volumes["Docker Volumes"]:::database end developer["Developer"]:::actor developer --> nginx nginx --> frontend nginx --> backend frontend --> backend backend --> postgres backend --> redis worker --> postgres worker --> redis

Docker Compose Dev

Developing modern applications requires more than just your code—you need a Database, a Redis cache, maybe an S3 emulator, and a Mail server. Installing these manually on every developer’s laptop is a recipe for “configuration drift.”

Docker Compose solves this by defining your entire infrastructure in a single YAML file. New hire? Run docker-compose up, and they are productive in minutes.

Architecture

We are automating the “localhost” infrastructure.

  • App Service: Your Node/Python/Go code, running with “Hot Reload” enabled.
  • Database: Postgres or MySQL, with persistent data in a Docker Volume.
  • Cache: Redis for session storage.
  • MailHog: A fake SMTP server for testing emails without spamming real users.

Use Cases

  • Onboarding: ” clone repo” -> “docker-compose up” -> “ready to code.”
  • Integration Testing: Spin up a fresh DB for CI/CD pipelines, run tests, and tear it down.
  • Polyglot Teams: Frontend devs don’t need to know how to install Python/Postgres locally; they just “run the container.”

Implementation Guide

We will create a robust environment for a Node.js app + Postgres + Redis + MailHog.

Prerequisites

  • Docker Desktop (or Engine)
  • Docker Compose

Step 1: Services Definition

Create docker-compose.yml.

version: '3.8'

services:
  # 1. The Application with Hot Reload
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules # Avoid overwriting container modules
    environment:
      - DATABASE_URL=postgres://user:password@db:5432/myapp
      - REDIS_URL=redis://cache:6379
      - SMTP_HOST=mailhog
    depends_on:
      - db
      - cache

  # 2. Database
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: myapp
    ports:
      - "5432:5432" # Expose to host for GUI tools
    volumes:
      - postgres_data:/var/lib/postgresql/data

  # 3. Cache
  cache:
    image: redis:7-alpine

  # 4. Email Testing
  mailhog:
    image: mailhog/mailhog
    ports:
      - "8025:8025" # Dashboard
      - "1025:1025" # SMTP

volumes:
  postgres_data:

Step 2: Optimizing the Dockerfile

Create Dockerfile.dev. Note that we install devDependencies here (like nodemon).

FROM node:18-alpine

WORKDIR /app

# Copy package.json first to leverage caching
COPY package*.json ./

# Install ALL dependencies (including dev)
RUN npm install

# We DON'T copy the source code here because we bind-mount it in docker-compose
# This makes image build faster and ensures 'hot reload' works.

EXPOSE 3000

# Use nodemon for hot reloading
CMD ["npx", "nodemon", "src/index.js"]

Step 3: Run It

docker-compose up

Access:

  • App: http://localhost:3000
  • MailHog UI: http://localhost:8025

Production Readiness Checklist

Wait, isn’t this for Dev? Yes, but your setup should reflect production reality.

[ ] .dockerignore: Ensure node_modules and .git are ignored to speed up builds. [ ] Versions: Pin image tags (e.g., postgres:15.2 NOT latest) to match Production DB exactly. [ ] Database Init: Use /docker-entrypoint-initdb.d/ in Postgres image to seed initial data. [ ] Healthchecks: Add healthcheck to your service definitions, so app waits until db is actually listening (not just started). [ ] User Permissions: On Linux, ensure the user ID inside the container matches your host user to avoid file permission errors (user: "${UID}:${GID}").

Cloud Cost Estimator

Dynamic Pricing Calculator

$0 / month
MVP (1x) Startup (5x) Growth (20x) Scale (100x)
MVP Level
Compute Resources
$ 15
Database Storage
$ 25
Load Balancer
$ 10
CDN / Bandwidth
$ 5
* Estimates vary by provider & region
0%
Your Progress 0 of 0 steps