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:
- Create complete docker-compose for your project (frontend + backend + DB + cache)
- Build multi-stage Dockerfile, reduce image from 1GB to 100MB
- Set up healthcheck and auto-restart
- Create dev/test/prod environment configs
- 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
upcommand 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
.dockerignoreto 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.