From cad5e9df2f3e4a5131b4290a9bad70d37534983a Mon Sep 17 00:00:00 2001 From: Craig Date: Tue, 9 Sep 2025 14:28:44 -0700 Subject: [PATCH] dhi: add single stage migration examples Signed-off-by: Craig --- content/manuals/dhi/how-to/migrate.md | 87 ++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/content/manuals/dhi/how-to/migrate.md b/content/manuals/dhi/how-to/migrate.md index 22b1d825d35f..5b561f50c057 100644 --- a/content/manuals/dhi/how-to/migrate.md +++ b/content/manuals/dhi/how-to/migrate.md @@ -63,6 +63,12 @@ replaced by the new hardened image. ### Step 2: Update the runtime image in your Dockerfile +> [!NOTE] +> +> Multi-stage builds are recommended to keep your final image minimal and +> secure. Single-stage builds are supported, but they include the full `dev` image +> and therefore result in a larger image with a broader attack surface. + To ensure that your final image is as minimal as possible, you should use a [multi-stage build](/manuals/build/building/multi-stage.md). All stages in your Dockerfile should use a hardened image. While intermediary stages will typically @@ -77,8 +83,15 @@ examples of how to update your Dockerfile. ## Example Dockerfile migrations -The following migration examples show a Dockerfile before the migration and -after the migration. +The following examples show a Dockerfile before and after migration. Each +example includes both a multi-stage build (recommended for minimal, secure +images) and a single-stage build (supported, but results in a larger image with +a broader attack surface). + +> [!NOTE] +> +> Multi-stage builds are recommended for most use cases. Single-stage builds are +> supported for simplicity, but come with tradeoffs in size and security. ### Go example @@ -98,7 +111,7 @@ ENTRYPOINT ["/app/main"] ``` {{< /tab >}} -{{< tab name="After" >}} +{{< tab name="After (multi-stage)" >}} ```dockerfile #syntax=docker/dockerfile:1 @@ -118,6 +131,22 @@ COPY --from=builder /app/main /app/main ENTRYPOINT ["/app/main"] ``` + +{{< /tab >}} +{{< tab name="After (single-stage)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM /dhi-golang:1-alpine3.21-dev + +WORKDIR /app +ADD . ./ +RUN CGO_ENABLED=0 GOOS=linux go build -a -ldflags="-s -w" --installsuffix cgo -o main . + +ENTRYPOINT ["/app/main"] +``` + {{< /tab >}} {{< /tabs >}} @@ -142,7 +171,7 @@ CMD ["node", "index.js"] ``` {{< /tab >}} -{{< tab name="After" >}} +{{< tab name="After (multi-stage)" >}} ```dockerfile #syntax=docker/dockerfile:1 @@ -167,6 +196,25 @@ WORKDIR /app CMD ["index.js"] ``` + +{{< /tab >}} +{{< tab name="After (single-stage)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM /dhi-node:23-alpine3.21-dev +WORKDIR /usr/src/app + +COPY package*.json ./ +RUN npm install + +COPY image.jpg ./image.jpg +COPY . . + +CMD ["index.js"] +``` + {{< /tab >}} {{< /tabs >}} @@ -206,7 +254,7 @@ ENTRYPOINT [ "python", "/app/image.py" ] ``` {{< /tab >}} -{{< tab name="After" >}} +{{< tab name="After (multi-stage)" >}} ```dockerfile #syntax=docker/dockerfile:1 @@ -240,12 +288,37 @@ COPY --from=builder /app/venv /app/venv ENTRYPOINT [ "python", "/app/image.py" ] ``` +{{< /tab >}} +{{< tab name="After (single-stage)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM /dhi-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 . +RUN pip install --no-cache-dir -r requirements.txt + +COPY image.py image.png ./ + +ENTRYPOINT [ "python", "/app/image.py" ] +``` + {{< /tab >}} {{< /tabs >}} ### Use Gordon -Alternatively, you can request assistance to -[Gordon](/manuals/ai/gordon/_index.md), Docker's AI-powered assistant, to migrate your Dockerfile: +Alternatively, you can request assistance to +[Gordon](/manuals/ai/gordon/_index.md), Docker's AI-powered assistant, to +migrate your Dockerfile: {{% include "gordondhi.md" %}}