Docker Dev Environment Template
A Docker Compose development environment template with hot reload, database, Redis, and Mailpit — ready for any Node.js/TypeScript project.
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