ta-training

Docker and Make

Docker provides a consistent runtime environment for all projects, and Make turns common multi-step workflows into single commands. Together they eliminate “it works on my machine” problems and make projects reproducible.


Why Docker + Make


Docker patterns

Modern Dockerfile with uv

FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim

WORKDIR /app

# Copy dependency files
COPY pyproject.toml uv.lock ./

# Install dependencies using uv
RUN uv sync --frozen --no-dev

# Copy source code
COPY . .

# Default command
CMD ["uv", "run", "python", "app.py"]

Best practices

Running with volume mounts

docker run --rm -it -v $(pwd):/app -w /app clinic-demo uv run python script.py

Makefile patterns

IMAGE=clinic-demo
TAG=latest

.PHONY: build run test lint shell clean sync

# Build Docker image
build:
	docker build -t $(IMAGE):$(TAG) .

# Run the main application
run:
	docker run --rm -it -v $(PWD):/app -w /app $(IMAGE):$(TAG) uv run python app.py

# Run tests
test:
	docker run --rm -it -v $(PWD):/app -w /app $(IMAGE):$(TAG) uv run pytest -q

# Run linting
lint:
	docker run --rm -it -v $(PWD):/app -w /app $(IMAGE):$(TAG) uv run ruff check .

# Interactive shell in container
shell:
	docker run --rm -it -v $(PWD):/app -w /app $(IMAGE):$(TAG) bash

# Sync dependencies (run after updating pyproject.toml)
sync:
	docker run --rm -it -v $(PWD):/app -w /app $(IMAGE):$(TAG) uv sync

# Clean up Docker images
clean:
	docker rmi $(IMAGE):$(TAG) || true

Wrap common Docker commands in a Makefile at the repo root:

Key differences from pip-based workflows

Dependency management:

Execution:

Performance benefits:

Examples