yaml DevOps January 10, 2026

Docker Dev Environment Template

A Docker Compose development environment template with hot reload, database, Redis, and Mailpit — ready for any Node.js/TypeScript project.

dockerdocker-composedevelopmentdevcontainernodejs

Description

A complete Docker Compose setup for local development. Includes a Node.js app with hot reload, PostgreSQL, Redis, and Mailpit for email testing. One docker compose up and you’re coding.

Features

  • Hot reload via bind mounts — edit code, see changes instantly
  • PostgreSQL 16 with health checks and persistent data
  • Redis 7 for caching and sessions
  • Mailpit for email testing with web UI
  • Network isolation between services
  • .env file support for configuration

Docker Compose

# docker-compose.dev.yml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    container_name: myapp-dev
    restart: unless-stopped
    ports:
      - "3000:3000"
      - "9229:9229"  # Node.js debugger
    volumes:
      - .:/app
      - /app/node_modules  # Don't override node_modules
    environment:
      - NODE_ENV=development
      - DATABASE_URL=postgresql://dev:devpass@db:5432/myapp
      - REDIS_URL=redis://redis:6379
      - SMTP_HOST=mailpit
      - SMTP_PORT=1025
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    command: npm run dev

  db:
    image: postgres:16-alpine
    container_name: myapp-db
    restart: unless-stopped
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: devpass
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dev"]
      interval: 5s
      timeout: 3s
      retries: 5

  redis:
    image: redis:7-alpine
    container_name: myapp-redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    command: redis-server --appendonly yes
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5

  mailpit:
    image: axllent/mailpit:latest
    container_name: myapp-mail
    restart: unless-stopped
    ports:
      - "8025:8025"  # Web UI
      - "1025:1025"  # SMTP
    environment:
      MP_SMTP_AUTH_ACCEPT_ANY: 1
      MP_SMTP_AUTH_ALLOW_INSECURE: 1

volumes:
  pgdata:
  redisdata:

Dev Dockerfile

# Dockerfile.dev
FROM node:20-alpine

WORKDIR /app

# Install dependencies first (caching layer)
COPY package*.json ./
RUN npm install

# Copy source (overridden by bind mount in dev)
COPY . .

# Expose app + debugger ports
EXPOSE 3000 9229

# Start with hot reload
CMD ["npm", "run", "dev"]

Environment File

# .env.development
NODE_ENV=development
DATABASE_URL=postgresql://dev:devpass@localhost:5432/myapp
REDIS_URL=redis://localhost:6379
SMTP_HOST=localhost
SMTP_PORT=1025
JWT_SECRET=dev-secret-do-not-use-in-production

Makefile Targets

# Dev environment management
dev:
	docker compose -f docker-compose.dev.yml up

dev-build:
	docker compose -f docker-compose.dev.yml up --build

dev-down:
	docker compose -f docker-compose.dev.yml down

dev-reset:
	docker compose -f docker-compose.dev.yml down -v
	docker compose -f docker-compose.dev.yml up --build

dev-logs:
	docker compose -f docker-compose.dev.yml logs -f app

dev-shell:
	docker compose -f docker-compose.dev.yml exec app sh

dev-db:
	docker compose -f docker-compose.dev.yml exec db psql -U dev myapp

Usage

# Start everything
docker compose -f docker-compose.dev.yml up

# Access services:
#   App:     http://localhost:3000
#   Mailpit: http://localhost:8025
#   DB:      localhost:5432
#   Redis:   localhost:6379

# Reset everything (including data)
docker compose -f docker-compose.dev.yml down -v