Use a Docker Hardened Image
You can use a Docker Hardened Image (DHI) just like any other image on Docker
Hub. DHIs follow the same familiar usage patterns. Pull them with docker pull,
reference them in your Dockerfile, and run containers with docker run.
The key difference is that DHIs are security-focused and intentionally minimal to reduce the attack surface. This means some variants don't include a shell or package manager, and may run as a non-root user by default.
ImportantYou must authenticate to the Docker Hardened Images registry (
dhi.io) to pull DHI Community images. You can authenticate using either of the following:
- Docker ID and password: Use your Docker Hub username and password. If you don't have a Docker account, create one for free.
- Access token: Use a personal access token (PAT) for personal accounts, or an organization access token (OAT) with your organization name as the username.
Run
docker login dhi.ioto authenticate.
Considerations when adopting DHIs
Docker Hardened Images are intentionally minimal to improve security. If you're updating existing Dockerfiles or frameworks to use DHIs, keep in mind that runtime images don't include shells or package managers, run as non-root users by default, and may have different configurations than images you're familiar with.
For a comprehensive checklist of migration considerations and detailed guidance, see Migrate to Docker Hardened Images.
Pull, run, and reference DHIs
Docker Hardened Images use different image references depending on your subscription:
| Subscription | Image reference | Authentication |
|---|---|---|
| Community | dhi.io/<image>:<tag> | docker login dhi.io |
| Select & Enterprise | <your-org>/<image>:<tag> | docker login |
Select and Enterprise users should mirror repositories to their Docker Hub organization to access compliance variants and customization features.
After authenticating, use the image reference in standard Docker commands and Dockerfiles. For example:
$ docker pull dhi.io/python:3.13
$ docker run --rm dhi.io/python:3.13 python -c "print('Hello from DHI')"
FROM dhi.io/python:3.13
COPY . /app
CMD ["python", "/app/main.py"]For multi-stage builds:
- Use a
-devtag for build stages that need a shell or package manager. See Use dev variants for framework-based applications. - Use the
staticimage for compiled executables with minimal runtime dependencies. See Use a static image for compiled executables.
To learn how to search for available variants, see Search and evaluate images.
Use a DHI in CI/CD pipelines
Docker Hardened Images work just like any other image in your CI/CD pipelines. You can reference them in Dockerfiles, pull them as part of a pipeline step, or run containers based on them during builds and tests.
Unlike typical container images, DHIs also include signed attestations such as SBOMs and provenance metadata. You can incorporate these into your pipeline to support supply chain security, policy checks, or audit requirements if your tooling supports it.
To strengthen your software supply chain, consider adding your own attestations when building images from DHIs. This lets you document how the image was built, verify its integrity, and enable downstream validation and policy enforcement using tools like Docker Scout.
To learn how to attach attestations during the build process, see Docker Build Attestations.
Use a static image for compiled executables
Docker Hardened Images include a static image repository designed specifically
for running compiled executables in an extremely minimal and secure runtime.
Unlike a non-hardened FROM scratch image, the DHI static image includes
attestations and essential packages like ca-certificates.
Use a -dev or other builder image to compile your binary, then copy the output
into a static image:
FROM dhi.io/golang:1.22-dev AS build
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o myapp
FROM dhi.io/static:20230311
COPY --from=build /app/myapp /myapp
ENTRYPOINT ["/myapp"]For more multi-stage build patterns, see the Go migration example.
Use dev variants for framework-based applications
If you're building applications with frameworks that require package managers or
build tools (such as Python, Node.js, or Go), use a -dev variant during the
development or build stage. These variants include essential utilities like
shells, compilers, and package managers to support local iteration and CI
workflows.
Use -dev images in your inner development loop or in isolated CI stages to
maximize productivity. Once you're ready to produce artifacts for production,
switch to a smaller runtime variant to reduce the attack surface and image size.
For detailed multi-stage Dockerfile examples using dev variants, see the migration examples:
Use compliance and ELS variants DHI Select & Enterprise
With a DHI Select or DHI Enterprise subscription, you can access additional image variants:
- Compliance variants: FIPS-enabled and STIG-ready images for regulatory requirements
- ELS (Extended Lifecycle Support) variants (requires add-on): Security patches for end-of-life image versions
To access these variants, mirror the repository to your Docker Hub organization. For ELS, enable Mirror end-of-life images when setting up mirroring. Once mirrored, use the compliance or EOL tags like any other image tag.
Use with Kubernetes
When deploying Docker Hardened Images to Kubernetes, the process is similar to
using any other container image with one key difference: you must configure
image pull secrets to authenticate to the DHI registry. This applies whether
you're pulling directly from dhi.io, from a mirror on Docker Hub, or from
your own third-party registry.
Create an image pull secret
You can create an image pull secret using either an access token or Docker Desktop credentials.
For the --docker-server value:
- Use
dhi.iofor community images pulled directly from Docker Hardened Images - Use
docker.iofor mirrored repositories on Docker Hub - Use your registry's hostname for third-party registries
Using an access token
Create a secret using a Personal Access Token (PAT) or Organization Access Token (OAT). Ensure the token has at least read-only access to the repositories.
$ kubectl create -n <kubernetes namespace> secret docker-registry <secret name> --docker-server=<registry server> \
--docker-username=<registry user> --docker-password=<access token> \
--docker-email=<registry email>
Using Docker Desktop credentials
If you're already authenticated with Docker Desktop, you can create a secret
using your stored credentials. This method works for registries you've
authenticated to via Docker Desktop (using docker login <registry>).
$ NS=<namespace>
$ kubectl create -n ${NS} secret docker-registry dhi-pull-secret \
--docker-server=<registry server> \
--docker-username=<registry user> \
--docker-password="$(echo https://<registry server> | docker-credential-desktop get | jq -r .Secret)" \
--docker-email=<registry email>
This method extracts credentials from Docker Desktop's credential store, avoiding the need to create a separate access token for local development.
Test the image pull secret
After creating the secret, verify it works by deploying a test pod that
references the secret in its imagePullSecrets configuration.
Create a test pod:
kubectl apply --wait -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: dhi-test
namespace: <kubernetes namespace>
spec:
containers:
- name: test
image: bash:5
command: [ "sh", "-c", "echo 'Hello from DHI in Kubernetes!'" ]
imagePullSecrets:
- name: <secret name>
EOF
Check the pod status to ensure it completed successfully:
$ kubectl get -n <kubernetes namespace> pods/dhi-test
A successful test shows Completed status:
NAME READY STATUS RESTARTS AGE
dhi-test 0/1 Completed ... ...
If you see ErrImagePull status instead, there's an issue with your secret
configuration:
NAME READY STATUS RESTARTS AGE
dhi-test 0/1 ErrImagePull 0 ...
Verify the pod output matches the expected message:
$ kubectl logs -n <kubernetes namespace> pods/dhi-test
Hello from DHI in Kubernetes!
Clean up the test pod:
$ kubectl delete -n <kubernetes namespace> pods/dhi-test