Docker & Compose Proficient¶
🚀 Deployment · Level 4
When you'd use this
Dockerfiles, multi-stage builds, docker-compose and container best practices.
Package an app and its dependencies into a reproducible container that runs the same everywhere.
Dockerfile for Python apps¶
A multi-stage build that produces a small, reproducible image for a Python service.
# ─── Multi-stage build (smaller final image) ─────
FROM python:3.13-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
FROM python:3.13-slim
WORKDIR /app
COPY --from=builder /install /usr/local
COPY src/ ./src/
COPY pyproject.toml .
# Non-root user (security best practice)
RUN useradd -m appuser
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
docker-compose (local dev environment)¶
Spin up your app plus its dependencies (DB, cache) with one command for local dev.
# docker-compose.yml
services:
app:
build: .
ports: ["8000:8000"]
environment:
DATABASE_URL: postgresql://postgres:secret@db:5432/myapp
REDIS_URL: redis://cache:6379
depends_on:
db: { condition: service_healthy }
cache: { condition: service_started }
volumes:
- ./src:/app/src # hot reload in dev
db:
image: postgres:16
environment:
POSTGRES_DB: myapp
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5
cache:
image: redis:7-alpine
ports: ["6379:6379"]
volumes:
pgdata:
docker compose up -d # start all services
docker compose logs -f app # follow app logs
docker compose down # stop and remove
docker compose exec app bash # shell into container
Best practices¶
Slim images, non-root users, pinned deps, and .dockerignore for safe, lean containers.
Docker for Python
- Use
python:3.13-slim(not full image — 5x smaller) - Use multi-stage builds (separate build deps from runtime)
- Pin dependency versions (reproducible builds)
- Run as non-root user
- Add
.dockerignore(exclude.git,__pycache__,.venv,tests/) - Use
HEALTHCHECKfor orchestrators to monitor
Practice Exercises¶
- Dockerize a FastAPI app with multi-stage build, non-root user and health check.
- Create docker-compose for app + PostgreSQL + Redis with proper health checks.
- Optimize image size — compare full vs slim vs alpine, measure with
docker images. - Add hot reload for development using volume mounts.
- Build a CI pipeline that builds Docker image and pushes to Docker Hub.
💬 Discussion
Have a question about this topic? Found an error? Share your thoughts below.