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. Use your Docker ID credentials (the same username and password you use for Docker Hub). If you don't have a Docker account, create one for free.Run
docker 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" ]