Docker for Development

Docker gives you reproducible environments — no more "works on my machine." Here's a practical setup for Django projects.

Dockerfile

FROM python:3.12-slim

WORKDIR /app

# Install dependencies first (layer caching)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .

# Collect static files at build time
RUN python manage.py collectstatic --noinput

EXPOSE 8000

CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]

Docker Compose for Local Dev

# docker-compose.yml
services:
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/app          # Live reload
    ports:
      - "8000:8000"
    environment:
      - DEBUG=1
      - DATABASE_URL=sqlite:///data/storydatabase.sqlite

Key Principles

Layer ordering matters. Put things that change least (OS, dependencies) at the top. Application code goes last. This maximizes cache hits:

# Changes rarely → cached
COPY requirements.txt .
RUN pip install -r requirements.txt

# Changes often → rebuilt
COPY . .

Use .dockerignore. Keep images small:

.git
__pycache__
*.pyc
.env
node_modules
data/*.sqlite

Development vs. Production. Use docker-compose.override.yml for dev-only settings:

# docker-compose.override.yml (auto-loaded in dev)
services:
  web:
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/app
    environment:
      - DEBUG=1

Useful Commands

# Build and start
docker compose up --build

# Run management commands
docker compose exec web python manage.py migrate
docker compose exec web python manage.py seed_content

# Shell into container
docker compose exec web bash

# View logs
docker compose logs -f web