Docker Development Environment

"It works on my machine!" โ€” The ultimate cure for this classic line is Docker.

Docker makes your development environment identical to production, eliminating the nightmare of "works in dev, breaks in production."

๐Ÿ”ฅ Vibe Prompt

"Create a complete Docker development environment: multi-service docker-compose with Python FastAPI backend, PostgreSQL database, Redis cache, with dev/staging/production environment separation."

Docker Core Concepts

| Concept | Description | Analogy | |---------|-------------|---------| | Image | Read-only template with runtime and code | Like an ISO install disk | | Container | Running instance of an Image | Like an installed OS | | Dockerfile | Script describing how to build an Image | Like installation manual | | Volume | Persistent data, independent of container lifecycle | Like an external hard drive | | Network | Virtual network for container communication | Like a LAN |

Dockerfile Best Practices

# Multi-stage Build
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Stage 2: Run (smaller Image)
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]

Docker Compose Multi-Service Setup

version: '3.8'

services:
  api:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "8000:8000"
    volumes:
      - .:/app
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/app
      - REDIS_URL=redis://cache:6379
    depends_on:
      - db
      - cache

  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=app

  cache:
    image: redis:7-alpine

volumes:
  pgdata:

Environment Differences

| Aspect | Development | Production | |--------|-------------|------------| | Code loading | Volume mount with hot reload | Built into image | | Debugging | Debug port exposed | Disabled | | Logging | Verbose output | Structured JSON | | Database | Auto-reset | Persistent, backed up | | Scaling | Single instance | Multi-instance + LB |

Practice Exercise

๐Ÿ’ก Vibe Coding Practice: Ask AI to:

  1. Create complete docker-compose for your project (frontend + backend + DB + cache)
  2. Build multi-stage Dockerfile, reduce image from 1GB to 100MB
  3. Set up healthcheck and auto-restart
  4. Create dev/test/prod environment configs
  5. Build CI/CD Docker deployment scripts

Docker Development Environment

A Docker dev environment lets you run your entire application stack in containers โ€” consistent across all developers and deployment targets.

Why Docker for Development?

| Problem | Docker Solution | |---------|----------------| | "Works on my machine" | Same environment everywhere | | Installing dependencies | Pre-built images with all dependencies | | Version conflicts | Each service runs in its own container | | Team onboarding | Single docker compose up command | | Production parity | Same images in dev and production |

Docker Compose for Development

version: "3.9"
services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - ./frontend:/app  # Hot-reload
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - API_URL=http://backend:4000
    depends_on:
      - backend

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.dev
    ports:
      - "4000:4000"
    volumes:
      - ./backend:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DB_HOST=db
      - DB_USER=dev
      - DB_PASSWORD=devpass
      - DB_NAME=myapp_dev
    depends_on:
      db:
        condition: service_healthy

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

volumes:
  pg_data:

Dockerfile Best Practices

# Multi-stage build for production
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

# Security: run as non-root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

CMD ["node", "dist/server.js"]

Development Workflow

# Start all services
docker compose up -d

# View logs
docker compose logs -f

# Open a shell in a container
docker compose exec backend bash

# Run a command in a container
docker compose exec backend npm test

# Rebuild after dependency changes
docker compose build backend

# Stop everything
docker compose down

# Clean up volumes (reset database)
docker compose down -v

Best Practices

| Practice | Reason | |----------|--------| | Use .dockerignore | Prevents sending unnecessary files to Docker context | | Pin image versions | postgres:16-alpine not postgres:latest | | Use multi-stage builds | Smaller, more secure production images | | Run as non-root | Security best practice | | Add health checks | depends_on waits for real readiness | | Use named volumes | Data persists across container restarts | | Separate dev and prod configs | Different volume mounts, env vars | | Keep .env files out of Git | Use .env.example for documentation |

Summary

Docker Compose creates consistent development environments. Define services, volumes, and networks in YAML. Use multi-stage Dockerfiles for smaller images. Always run as non-root and add health checks.

Key takeaways:

  • Docker Compose = single up command runs entire stack
  • Volume mounts enable hot-reload during development
  • depends_on with healthcheck waits for real readiness
  • Multi-stage builds reduce image size by 50-90%
  • Non-root user improves security
  • Use .dockerignore to speed up builds
  • Separate dev and production Dockerfiles
  • Keep .env secrets out of version control

What's Next: Course Wrap-Up

This concludes the Developer Tools course. You now have essential tools and workflows for professional development.

Unlock Full Tutorial

This chapter is paid content. Join the project to unlock over 5000 words of deep analysis, including 10+ god-tier Prompts and real Source Code examples!