DEV Community

Cover image for Migration, Production Adoption, Hardened Packages & Real-World Patterns
Koti Vellanki
Koti Vellanki

Posted on

Migration, Production Adoption, Hardened Packages & Real-World Patterns

Docker Hardened Images Series — Blog 5 (Final)

What We Are Building

This final blog turns everything you have learned into a practical adoption plan.

You will:

  • Walk through a realistic migration of an existing Dockerfile
  • Use a clear migration checklist so nothing is missed
  • Understand when Community is enough and when Select/Enterprise becomes useful
  • Get a short overview of hardened system packages
  • Leave with a production checklist and honest limitations
  • See how Docker Hardened Images and Docker Sandboxes fit together

Why This Matters

Pulling a DHI and building a new service is easy.

Migrating an existing production service without breaking it is the real work.

Most failures happen because of the same few issues:

  • Missing shell or package manager in the runtime stage
  • Application cannot run as non-root
  • Trying to bind to a privileged port
  • Forgetting that secrets and tools do not belong in the final image

This blog gives you the checklist and the judgement to avoid those problems.

What You Should Know Before Starting

  • Full Hardened Images series (Blogs 1–4) completed
  • At least one existing Dockerfile you can migrate (we will use a typical example)

Migration Checklist (Print This)

Item What to do Why it fails if ignored
Base image Change FROM to a matching dhi.io/... variant Still using the old attack surface
Package management Install only in *-dev stage, copy artefacts Runtime image has no package manager
Shell commands Move all RUN that need a shell into the build stage Runtime image has no shell
Non-root user Ensure files are readable/executable by the non-root user (usually UID 65532) Permission denied at runtime
Ports Listen on ≥ 1025 inside the container Non-root cannot bind to privileged ports
TLS certificates Remove manual ca-certificates install steps Already present in DHI
ENTRYPOINT / CMD Inspect the DHI and adjust if needed Unexpected default entrypoint
Multi-stage Always use -dev for build, pure runtime for final Final image becomes large and less secure
Secrets Never bake secrets into layers They will be visible in the image history
Policy check Run docker scout policy ... --policy-bundle dhi/policies:latest Image may not meet the hardened standard

Step 1 — Realistic Migration Example

Before (typical official image)

FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 80
CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

After (proper DHI multi-stage)

# syntax=docker/dockerfile:1

FROM dhi.io/python:3.13-dev AS builder
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
RUN python -m venv /app/venv
ENV PATH="/app/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM dhi.io/python:3.13
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
ENV PATH="/app/venv/bin:$PATH"
WORKDIR /app
COPY --from=builder /app/venv /app/venv
COPY app.py .
EXPOSE 8000
CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

Key changes:

  • Build tools only in the first stage
  • Final image is minimal and non-root
  • Port moved above 1024
  • No unnecessary packages left behind

Build and test:

docker build -t migrated-app .
docker run --rm -p 8000:8000 migrated-app
docker scout policy migrated-app --policy-bundle dhi/policies:latest
Enter fullscreen mode Exit fullscreen mode

Step 2 — Community vs Select vs Enterprise (Honest View)

Need Community (free) Select Enterprise
Minimal, near-zero CVE images Yes Yes Yes
Signed SBOM + SLSA provenance Yes Yes Yes
FIPS / STIG variants No Yes Yes
7-day SLA for critical/high CVEs No Yes Yes
Customisations No Limited (5) Unlimited
Hardened system packages repository Public only Limited Full access
Extended lifecycle (post-EOL) No No Yes (add-on)

Practical recommendation

Start with Community for almost every service.

Move to Select/Enterprise only when you have a concrete compliance (FIPS/STIG) or SLA requirement.

Step 3 — Hardened System Packages (Short Overview)

Docker builds many system packages from source and signs them.

These packages are already inside the DHI base images.

Community users can also configure the public hardened package repositories in their own Dockerfiles if they need extra packages during a build stage.

Enterprise customers get a private repository with broader access and longer support.

For most applications you will never need to touch this — the base image already contains the hardened packages you need.

Step 4 — Production Adoption Checklist

  • [ ] Every new service starts from a DHI base
  • [ ] Existing services have a migration ticket and a deadline
  • [ ] Multi-stage pattern is the team standard
  • [ ] CI always authenticates to dhi.io and runs the DHI policy bundle
  • [ ] Policy failures block the merge
  • [ ] Images are scanned and attested in the pipeline
  • [ ] Non-root and high ports are verified in staging
  • [ ] Team knows how to use docker scout attest and docker scout policy
  • [ ] Old official base images are removed from the allowed list

Step 5 — Combining with Docker Sandboxes

The two series fit together cleanly:

  • Developers use Docker Sandboxes so AI agents can work safely
  • Those same agents (or the CI) build application images from Docker Hardened Images
  • The final artefact that reaches production is both built in an isolated environment and based on a hardened, attested base

This gives you strong isolation during development and strong supply-chain guarantees at runtime.

Realistic Limitations (Be Honest)

  • Runtime images have no shell → debugging needs docker debug, a sidecar, or a temporary -dev container
  • Some legacy applications still expect to run as root or bind to port 80 → you must change the application or use a workaround
  • Community tier has no SLA — patch timing follows upstream + Docker’s cadence
  • Very exotic native dependencies may not yet exist as hardened packages
  • Organisation governance (for Sandboxes) and DHI Select/Enterprise are separate paid offerings

Common Migration Pitfalls

  • Leaving a USER root statement “just in case”
  • Installing packages in the final stage
  • Forgetting to update health-check or readiness probes that assumed port 80
  • Assuming every tag has a -dev variant (check the catalog)
  • Migrating only the base image and leaving the rest of the Dockerfile unchanged

Troubleshooting Quick Reference

Symptom Most common cause Fix
exec: "bash": executable not found Runtime image used for a shell command Move the command to a -dev stage
Permission denied Non-root user cannot write Fix ownership with COPY --chown or in builder
Address already in use / bind error Trying to use port < 1024 Change application to listen on ≥ 1025
Policy fails on “shell present” Final stage still has a shell Use pure runtime variant
Cannot pull in CI Missing docker login dhi.io Add the login step shown in Blog 4

Cleanup

docker rmi migrated-app 2>/dev/null || true
Enter fullscreen mode Exit fullscreen mode

What We Learned in the Whole Hardened Images Series

  1. Why typical images need hardening and how to pull the first DHI
  2. Anatomy of runtime vs dev variants and how to build real applications
  3. SBOMs, provenance, signatures and how to enforce the same policies
  4. Production multi-stage Dockerfiles + CI gates
  5. Migration checklist, tier decisions, limitations and how to adopt safely

You now have a complete, practical path from “I have heard of hardened images” to “I can migrate and run them in production with confidence”.

Final Combined Recommendation

  • Use Docker Sandboxes for any AI coding agent work
  • Use Docker Hardened Images as the base for every application image
  • Enforce both with clear team defaults and automated checks

That combination gives you strong isolation during development and a minimal, attested, continuously maintained runtime in production.

References

All technical claims verified against current official documentation (August 2026).


Top comments (0)