Python
This example shows how to migrate a Python application to Docker Hardened Images.
The following examples show Dockerfiles before and after migration to Docker Hardened Images. Each example includes five variations:
- Before (Ubuntu): A sample Dockerfile using Ubuntu-based images, before migrating to DHI
- Before (Wolfi): A sample Dockerfile using Wolfi distribution images, before migrating to DHI
- Before (DOI): A sample Dockerfile using Docker Official Images, before migrating to DHI
- After (multi-stage): A sample Dockerfile after migrating to DHI with multi-stage builds (recommended for minimal, secure images)
- After (single-stage): A sample Dockerfile after migrating to DHI with single-stage builds (simpler but results in a larger image with a broader attack surface)
NoteMulti-stage builds are recommended for most use cases. Single-stage builds are supported for simplicity, but come with tradeoffs in size and security.
You must authenticate to
dhi.iobefore you can pull Docker Hardened Images. Rundocker login dhi.ioto authenticate.
#syntax=docker/dockerfile:1 FROM ubuntu/python:3.13-24.04_stable AS builder ENV LANG=C.UTF-8 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 ENV PATH="/app/venv/bin:$PATH" WORKDIR /app RUN python -m venv /app/venv COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt FROM ubuntu/python:3.13-24.04_stable WORKDIR /app ENV PYTHONUNBUFFERED=1 ENV PATH="/app/venv/bin:$PATH" COPY app.py ./ COPY --from=builder /app/venv /app/venv ENTRYPOINT [ "python", "/app/app.py" ]#syntax=docker/dockerfile:1 FROM cgr.dev/chainguard/python:latest-dev AS builder ENV LANG=C.UTF-8 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 ENV PATH="/app/venv/bin:$PATH" WORKDIR /app RUN python -m venv /app/venv COPY requirements.txt . # Install any additional packages if needed using apk # RUN apk add --no-cache gcc musl-dev RUN pip install --no-cache-dir -r requirements.txt FROM cgr.dev/chainguard/python:latest WORKDIR /app ENV PYTHONUNBUFFERED=1 ENV PATH="/app/venv/bin:$PATH" COPY app.py ./ COPY --from=builder /app/venv /app/venv ENTRYPOINT [ "python", "/app/app.py" ]#syntax=docker/dockerfile:1 FROM python:latest AS builder ENV LANG=C.UTF-8 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 ENV PATH="/app/venv/bin:$PATH" WORKDIR /app RUN python -m venv /app/venv COPY requirements.txt . # Install any additional packages if needed using apt # RUN apt-get update && apt-get install -y gcc && rm -rf /var/lib/apt/lists/* RUN pip install --no-cache-dir -r requirements.txt FROM python:latest WORKDIR /app ENV PYTHONUNBUFFERED=1 ENV PATH="/app/venv/bin:$PATH" COPY app.py ./ COPY --from=builder /app/venv /app/venv ENTRYPOINT [ "python", "/app/app.py" ]#syntax=docker/dockerfile:1 # === Build stage: Install dependencies and create virtual environment === FROM dhi.io/python:3.13-alpine3.21-dev AS builder ENV LANG=C.UTF-8 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 ENV PATH="/app/venv/bin:$PATH" WORKDIR /app RUN python -m venv /app/venv COPY requirements.txt . # Install any additional packages if needed using apk # RUN apk add --no-cache gcc musl-dev RUN pip install --no-cache-dir -r requirements.txt # === Final stage: Create minimal runtime image === FROM dhi.io/python:3.13-alpine3.21 WORKDIR /app ENV PYTHONUNBUFFERED=1 ENV PATH="/app/venv/bin:$PATH" COPY app.py ./ COPY --from=builder /app/venv /app/venv ENTRYPOINT [ "python", "/app/app.py" ]#syntax=docker/dockerfile:1 FROM dhi.io/python:3.13-alpine3.21-dev ENV LANG=C.UTF-8 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 ENV PATH="/app/venv/bin:$PATH" WORKDIR /app RUN python -m venv /app/venv COPY requirements.txt . # Install any additional packages if needed using apk # RUN apk add --no-cache gcc musl-dev RUN pip install --no-cache-dir -r requirements.txt COPY app.py ./ ENTRYPOINT [ "python", "/app/app.py" ]