# Docker Deployment

> Docker, docker-compose, and deployment configuration best practices. Use when writing Dockerfiles, docker-compose.yml, CI/CD configs, or setting up any containerized deployment.

- Skill: `majiayu000/docker-deployment-3` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/docker-deployment-3`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/docker-deployment-3/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/docker-deployment-3

---


# Docker Deployment Patterns

## Production Dockerfile (Python)
```dockerfile
FROM python:3.12-slim AS base
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1

FROM base AS builder
RUN pip install --no-cache-dir uv
COPY requirements.txt .
RUN uv pip install --system --no-cache -r requirements.txt

FROM base AS runtime
COPY --from=builder /usr/local/lib/python3.12 /usr/local/lib/python3.12
COPY --from=builder /usr/local/bin /usr/local/bin
COPY . .
RUN useradd -m appuser && chown -R appuser /app
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
```

## docker-compose.yml (Development)
```yaml
services:
  app:
    build: .
    ports: ["8000:8000"]
    volumes: ["./:/app"]  # hot reload in dev
    env_file: [.env]
    depends_on:
      db: { condition: service_healthy }
      redis: { condition: service_healthy }
    command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes: [postgres_data:/var/lib/postgresql/data]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
      interval: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s

volumes:
  postgres_data:
```

## .env.example (Always provide this)
```bash
# Database
DB_HOST=db
DB_PORT=5432
DB_NAME=myapp
DB_USER=myapp
DB_PASSWORD=changeme_in_production

# Redis
REDIS_URL=redis://redis:6379/0

# App
SECRET_KEY=changeme_in_production
DEBUG=false
ALLOWED_ORIGINS=http://localhost:3000
```

## Makefile
```makefile
.PHONY: dev build test migrate

dev:
	docker-compose up --build

build:
	docker-compose build

test:
	docker-compose run --rm app pytest

migrate:
	docker-compose run --rm app alembic upgrade head

shell:
	docker-compose exec app bash
```

## Rules
- Multi-stage builds: keep final image small (no build tools)
- Never run as root — create appuser
- Health checks on ALL services
- Never hardcode secrets — always env vars
- .env.example with ALL required vars (no values)
- Volumes for persistent data (DB, uploads)
- Separate docker-compose.override.yml for dev overrides
- Pin image versions (postgres:16, not postgres:latest)

