Deploying Django backend microservices inside containerized environments requires keeping production images secure and fast to download. A standard Dockerfile that copies all project source files, builds libraries, and executes tasks in a single layer results in heavy images containing test suites, build caches, and dev packages. Multi-Stage Docker builds solve this by compiling code in temporary builder stages and copying only runtime files to the production image.
By partitioning builder tools and separating runtime environments, you can reduce production images to under 200MB.
1. Production-Grade Multi-Stage Dockerfile
We write a Dockerfile that compiles wheel packages in a builder stage and copies them to a clean runtime stage:
# Dockerfile
FROM python:3.9-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y build-essential libpq-dev
COPY requirements.txt .
# Compile dependencies into wheels
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements.txt
FROM python:3.9-slim AS runner
WORKDIR /app
RUN apt-get update && apt-get install -y libpq5 && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/wheels /wheels
RUN pip install --no-cache /wheels/*
COPY . .
EXPOSE 8000
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]
2. Handling Static Files and Migrations
The pipeline executes python manage.py collectstatic --noinput inside the Docker build loop, saving assets directly into a volume served by Nginx, keeping application deployments responsive.