DOCKERCONTAINERS
DOCKER FOR DEVELOPERS
Containerizing full-stack apps, multi-stage builds, and optimizing development workflows.
Why Docker Changes Everything
'Works on my machine' dies with Docker. Your development environment IS your production environment — all defined in docker-compose.yml, reproducible with one command.
Multi-Stage Builds
Don't ship your build tools. A Go API goes from 1.2GB to 15MB. A Next.js app drops to just production deps.
dockerfile
# Go API — multi-stage build
FROM golang:1.24-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server ./cmd/api
# Final image — just the binary
FROM alpine:3.19
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/server /server
EXPOSE 8080
CMD ["/server"]
# Result: ~15MB image vs 1.2GB with build toolsDocker Compose for Full Stack
Define your entire stack in one file. Use healthchecks, volumes for hot reload, and separate compose files for dev and prod.
yaml
# docker-compose.yml
services:
backend:
build: ./backend
ports: ["8080:8080"]
environment:
- DATABASE_URL=postgres://user:pass@postgres:5432/app
- REDIS_URL=redis://redis:6379
depends_on:
postgres: { condition: service_healthy }
redis: { condition: service_started }
volumes:
- ./backend:/app # hot reload in dev
frontend:
build: ./frontend
ports: ["3000:3000"]
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8080
volumes:
- ./frontend:/app
- /app/node_modules # don't override node_modules
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: app
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
redis:
image: redis:7-alpine
ports: ["6379:6379"]
volumes:
pgdata: