π³ Docker & Containers β
Containerizing applications for consistent environments and deployment.
Dockerfile best practices β
dockerfile
# Use specific version, not :latest
FROM node:20-alpine
WORKDIR /app
# Copy dependency files first (cache layer)
COPY package.json package-lock.json ./
RUN npm ci --production
# Copy source code
COPY . .
# Non-root user
RUN addgroup -S app && adduser -S app -G app
USER app
EXPOSE 3000
CMD ["node", "server.js"]Key principles β
- One process per container β Don't run multiple services in one container
- Minimize image size β Use Alpine, multi-stage builds
- Layer caching β Put rarely-changing layers first
- No secrets in images β Use env vars or mounted secrets
- Immutable images β Same image across all environments
Multi-stage build β
dockerfile
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build
# Production stage
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/server.js"]Docker Compose (local dev) β
yaml
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=pass
volumes:
pgdata:Common commands β
| Command | Purpose |
|---|---|
docker build -t app . | Build image |
docker run -p 3000:3000 app | Run container |
docker compose up -d | Start all services |
docker compose logs -f | Follow logs |
docker exec -it <id> sh | Shell into container |
docker system prune | Clean unused resources |