Customize a Docker Hardened Image or chart
When you have a DHI Select or DHI Enterprise subscription, you can customize Docker Hardened Images (DHI) and charts to suit your specific needs using the Docker Hub web interface. For images, this lets you select a base image, add packages, add OCI artifacts (such as custom certificates or additional tools), and configure settings. For charts, this lets you customize the image references.
Your customizations stay secure automatically. When the base Docker Hardened Image or chart receives a security patch or your OCI artifacts are updated, Docker automatically rebuilds your customizations in the background. This ensures continuous compliance and protection by default, with no manual work required. The rebuilt artifacts are signed and attested to the same SLSA Build Level 3 standard as the base images and charts, ensuring a secure and verifiable supply chain.
Customize a Docker Hardened Image
To add a customized Docker Hardened Image to your organization, an organization owner must first mirror the DHI repository to your organization on Docker Hub. Once the repository is mirrored, any user with access to the mirrored DHI repository can create a customized image.
You can create customizations using either the DHI CLI or the Docker Hub web interface.
Sign in to Docker Hub.
Select My Hub.
In the namespace drop-down, select your organization that has a mirrored DHI repository.
Select Hardened Images > Manage > Mirrored Images.
For the mirrored DHI repository you want to customize, select the menu icon in the far right column.
Select Customize.
At this point, the on-screen instructions will guide you through the customization process. You can continue with the following steps for more details.
Select one or more images or Helm charts and versions you want to customize.
When selecting multiple images and versions, all selections must share the same distribution and distribution version. For example, you can select
dhi-node:22_alpine3.23anddhi-python:3.13_alpine3.23together (both Alpine 3.23), but you cannot mixdhi-node:22_debianwith Alpine images, or mix different Alpine versions likealpine3.23andalpine3.22.Alternatively, you can select multiple Helm chart versions to apply the same customization to all of them. You cannot mix images and Helm charts in the same customization.
Select Next.
Optional. Add packages.
In the packages drop-down, select the packages you want to add to the image.
The packages available in the drop-down are OS system packages for the selected image variant. For version 3.23 Alpine-based images, these are hardened packages that have been built from source by Docker with cryptographic signatures and full supply chain security. For version 3.22 Alpine-based images and Debian-based images, these are standard system packages.
In the OCI artifacts drop-down, first, select the repository that contains the OCI artifact image. Then, select the tag you want to use from that repository. Finally, specify the specific paths you want to include from the OCI artifact image.
The OCI artifacts are images that you have previously built and pushed to a repository in the same namespace as the mirrored DHI. For example, you can add a custom root CA certificate or another image that contains a tool you need, like adding Python to a Node.js image. For more details on how to create an OCI artifact image, see Create an OCI artifact image.
You can add multiple OCI artifact images to a single customization. When you add more than one, they're applied in the order you add them in the OCI artifacts drop-down. If multiple images contain directories or files with the same path, images added later overwrite files from images added earlier. To manage this, you must select paths to include and optionally exclude from each OCI artifact image. This allows you to control which files are included in the final customized image.
By default, no files are included from the OCI artifact image. You must explicitly include the paths you want. After including a path, you can then explicitly exclude files or directories underneath it.
NoteWhen files necessary for runtime are overwritten by OCI artifacts, the image build still succeeds, but you may have issues when running the image.
In the Scripts section, you can add, edit, or remove scripts.
Scripts let you add files to the container image that you can access at runtime. They are not executed during the build process. This is useful for services that require pre-start initialization, such as setup scripts or file writes to directories like
/var/lockor/out.You must specify the following:
- The path where the script will be placed
- The script content
- The UID and GID ownership of the script
- The octal file permissions of the script
Select Next: Configure to configure the following image settings:
NoteWhen customizing multiple images at once, many of these configuration options are limited by default and may not be available.
- Specify the environment variables and their values that the image will contain.
- Add labels to the image.
- Add annotations to the image.
- Specify the users to add to the image. When you add a user, a home directory is automatically created for that user with 0755 permissions.
- Specify the user groups to add to the image.
- Select which user to run the images as.
- Add
ENTRYPOINTarguments to the image. These arguments are appended to the base image's entrypoint. - Add
CMDarguments to the image. These arguments are appended to the base image's command. - Override the default (
/) working directory for the image. - Specify a suffix for the customization name that is appended to the
customized image's tag. For example, if you specify
customwhen customizing thedhi-python:3.13image, the customized image will be tagged asdhi-python:3.13_custom. - Select the compression format for the image layers. You can choose between ZSTD (default) or GZIP compression. ZSTD typically provides faster image pulls and better compression ratios, but may have compatibility issues with older software. If you need compatibility with older Docker versions, use GZIP.
- Select the platforms you want to build the image for. You must select at least one platform.
Select Next: Review customization.
Select Create Customization.
A summary of the customization appears. It may take some time for the image to build. Once built, it will appear in the Tags tab of the repository, and your team members can pull it like any other image.
Authenticate with docker login using your Docker credentials or a personal
access token (PAT) with Read & Write
permissions, or an organization access token
(OAT). When using an OAT, the
available operations depend on the token's permission scope:
- To list or get customizations, or to view build logs, the OAT must have read (pull) access to the destination repository. Results are scoped to repositories the OAT can access.
- To create, update, or delete a customization, the OAT must have push access to the destination repository. Bulk operations require push access to every referenced destination repository.
Use the
docker dhi customization command:
# Prepare a single customization scaffold
$ docker dhi customization prepare golang 1.25 \
--org my-org \
--destination my-org/dhi-golang \
--name "golang with git" \
> my-customization.yaml
# Prepare a bulk customization scaffold (pipe JSON array via stdin)
$ echo '[{"destination":"my-org/dhi-golang","tag-definition-id":"golang/alpine-3.23/1.24-dev"}]' \
| docker dhi customization prepare --name "golang with git" --org my-org \
> my-customization.yaml
# Create a customization
$ docker dhi customization create my-customization.yaml --org my-org
# List customizations
$ docker dhi customization list --org my-org
# Filter customizations by name, repository, or source
$ docker dhi customization list --org my-org --filter git
$ docker dhi customization list --org my-org --repo dhi-golang
$ docker dhi customization list --org my-org --source golang
# Get a customization by ID
$ docker dhi customization get <id> --org my-org
# Update a customization
$ docker dhi customization edit my-customization.yaml --org my-org
# Delete a customization by ID
$ docker dhi customization delete <id> --org my-org
# Delete without confirmation prompt
$ docker dhi customization delete <id> --org my-org --force
For a complete reference of all YAML fields, see Image customization YAML file.
You can manage DHI customizations as infrastructure-as-code using the DHI Terraform provider. If you haven't configured the provider yet, see the Terraform tab in Mirror a repository for setup instructions.
Define a dhi_customization resource for each customization:
resource "dhi_customization" "golang_with_git" {
repository = "dhi-golang"
name = "golang with git"
contents {
packages = ["git", "curl"]
}
platform {
os = "linux"
architecture = "amd64"
}
}The dhi_customization resource also supports optional configuration blocks
for accounts, files, labels, annotations, environment, entrypoint,
cmd, user, workdir, and stop_signal.
Run terraform apply to create the customization.
To edit a customization, update the resource configuration and run terraform apply. To delete a customization, remove the resource and run terraform apply.
For the full list of resource attributes, see the Terraform Registry documentation.
NoteMonitoring customization builds is not available through the Terraform provider. Use the Docker Hub web interface or the DHI CLI to monitor builds.
Image customization YAML file
When using the CLI, customizations are defined in a YAML file. Use
docker dhi customization prepare to generate a scaffold with all available
fields and commented-out examples. Edit the file to describe what you want,
then pass it to docker dhi customization create.
The file has two parts: a preamble that identifies the customization and its targets, and a configuration section that specifies what to change.
About the id field
The id field is assigned automatically by Docker Hub when you run
docker dhi customization create. When creating a new customization, omit
id entirely. It is read-only.
To find the ID of an existing customization, run:
$ docker dhi customization list --org my-org
The id appears in the output and in files retrieved with
docker dhi customization get <id> --org my-org. It lets
docker dhi customization edit identify which customization to update.
Scaffolds from docker dhi customization prepare do not include id, and
that is expected.
Set targets
The name and targets fields are required in every customization file. The
targets array specifies which image versions the customization applies to.
Use a single entry for a single-image customization, or multiple entries for a
bulk customization that applies the same configuration to several images at
once.
name: golang with git
targets:
- destination: my-org/dhi-golang
tag_definition_id: golang/alpine-3.23/1.25| Field | Description |
|---|---|
name | Human-readable name. Converted to lowercase and hyphenated, it becomes the image tag suffix. For example, golang with git produces tags ending in _golang-with-git. |
targets[].destination | Destination repository in Docker Hub, such as my-org/dhi-golang. |
targets[].tag_definition_id | Tag definition to customize, such as golang/alpine-3.23/1.25. Use docker dhi customization prepare with tab completion to find valid values. |
NoteWhen
targetshas more than one entry, the fieldsaccounts,entrypoint, andcmdare not supported. Including them causesdocker dhi customization createto return an error.
Add packages
To install additional OS packages in your customized image, list them under
contents.packages. Available packages depend on the base image variant.
contents:
packages:
- git
- curlAdd OCI artifacts
To layer additional files into your customized image, such as custom
certificates, internal tools, or configuration files, list OCI artifact
images under contents.artifacts.
contents:
artifacts:
- name: my-org/my-certs:latest
includes:
- etc/ssl/certs
excludes:
- etc/ssl/certs/old| Field | Description |
|---|---|
name | Image reference of the OCI artifact. Must be in the same Docker Hub namespace as the mirrored DHI. |
includes | Paths to copy from the artifact. No files are included by default. You must list at least one path. |
excludes | Paths to exclude after applying includes. |
For instructions on building an OCI artifact image, see Create an OCI artifact image.
Inject files into the image
To add static files at build time, such as configuration files or startup
scripts, use the paths field. Files are added as static content and are not
executed during the build.
paths:
- path: /etc/myconfig
contents: |
key=value
mode: "0644"
uid: 0
gid: 0| Field | Description |
|---|---|
path | Absolute path where the file will be placed in the image. |
contents | File content. Use a YAML block scalar (|) for multi-line content. |
mode | Octal file permissions, such as "0644". Quote the value to prevent YAML from treating the leading zero as octal notation. |
uid | User ID of the file owner. |
gid | Group ID of the file owner. |
Configure user accounts
To add users or groups to the image, or to change which user the container
runs as, use the accounts field.
NoteNot supported for bulk customizations (multiple
targets).
accounts:
root: true
runs-as: nonroot
users:
- name: nonroot
uid: 65532
gid: 65532
groups:
- name: nonroot
gid: 65532
members:
- nonroot| Field | Description |
|---|---|
root | Whether to enable the root user. Default is false. Required if runs-as is set to root. |
runs-as | The default user the container runs as. |
users[].name | Username. |
users[].uid | User ID. |
users[].gid | Primary group ID. Optional. |
groups[].name | Group name. |
groups[].gid | Group ID. |
groups[].members | Usernames to add to this group. Optional. |
Set environment variables
To add or override environment variables in the image, use the environment
field. These are merged with the base image's existing environment and do not
replace it.
environment:
MY_VAR: my_value
DEBUG: "false"Quote values that a YAML parser would interpret as non-string types, for
example "false", "0", and "null".
Set labels and annotations
To add OCI metadata to the image, use labels and annotations. Labels are
stored in the image config; annotations are stored in the image manifest. Use
OCI standard keys
where applicable.
labels:
org.opencontainers.image.authors: your-email@example.com
org.opencontainers.image.version: "1.0.0"
annotations:
org.opencontainers.image.title: Custom hardened image
org.opencontainers.image.description: Customized Docker Hardened ImageOverride entrypoint and command
To change how the container starts, use entrypoint and cmd. These arguments
are appended to the base image's existing entrypoint and command.
NoteNot supported for bulk customizations (multiple
targets).
entrypoint:
- /docker-entrypoint.sh
cmd:
- /bin/bashSet platforms and compression
To build for multiple architectures, list them under platforms. At least one
platform is required.
platforms:
- linux/amd64
- linux/arm64To control layer compression, set compression. ZSTD (the default) offers
better compression and faster pulls. Use GZIP for compatibility with older
tooling.
compression: ZSTDCreate an OCI artifact image
An OCI artifact image is a Docker image that contains files or directories that you want to include in your customized Docker Hardened Image (DHI). This can include additional tools, libraries, or configuration files.
When creating an image to use as an OCI artifact, it should ideally be as minimal as possible and contain only the necessary files.
For example, to distribute a custom root CA certificate as part of a trusted CA bundle, you can use a multi-stage build. This approach registers your certificate with the system and outputs an updated CA bundle, which can be extracted into a minimal final image:
# syntax=docker/dockerfile:1
FROM dhi.io/bash:5-dev AS certs
ENV DEBIAN_FRONTEND=noninteractive
RUN mkdir -p /usr/local/share/ca-certificates/my-rootca
COPY certs/rootCA.crt /usr/local/share/ca-certificates/my-rootca
RUN update-ca-certificates
FROM scratch
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crtYou can follow this pattern to create other OCI artifacts, such as images
containing tools or libraries that you want to include in your customized DHI.
Install the necessary tools or libraries in the first stage, and then copy the
relevant files to the final stage that uses FROM scratch. This ensures that
your OCI artifact is minimal and contains only the necessary files.
In order for the OCI artifact to be available in a DHI customization, it must be built and pushed to a repository in the same namespace as the mirrored DHI repository.
If you're customizing a DHI for multiple platforms (such as linux/amd64 and
linux/arm64), build your OCI artifact for all the platforms using the
--platform flag:
$ docker buildx build --platform linux/amd64,linux/arm64 \
-t <your-namespace>/my-oci-artifact:latest \
--push .
This creates a single image manifest that you can use for each platform. The customization build system automatically selects the correct platform variant when building each customized image.
ImportantThe customization UI will only allow you to select platforms that are available in all OCI artifacts you've added. If a platform is missing from any OCI artifact, you won't be able to select that platform for your customization.
Once pushed to a repository in your organization's namespace, the OCI artifact automatically appears in the customization workflow when you select OCI artifacts to add to your customized Docker Hardened Image.
Best practices for OCI artifacts
Follow these best practices when creating OCI artifacts for DHI customizations:
Use multi-stage builds: Build or install dependencies in a builder stage, then copy only the necessary files to a
FROM scratchfinal stage. This keeps the OCI artifact minimal and free of unnecessary build tools.Include only essential files: OCI artifacts should contain only the files you need to add to the customized image. Avoid including package managers, shells, or other utilities that won't be used in the final image.
Match target platforms: Build your OCI artifact for all platforms you plan to use in your customizations. Use
docker buildx build --platformto create multi-platform images when needed.Use specific tags: Tag your OCI artifacts with specific versions or dates (like
v1.0or20250101) rather than relying solely onlatest. This ensures reproducible builds and makes it easier to track which artifacts are used in which customizations.Enable immutable tags: Consider enabling immutable tags for your OCI artifact repositories. This prevents accidental overwrites and ensures that each version of your OCI artifact remains unchanged, improving reproducibility and reliability of your customizations.
Customize a DHI Helm chart
You can customize DHI Helm charts to meet your organization's specific needs. Via the Docker Hub web interface, you can modify the image references to reference mirrored images or customized images you've created. This lets you create a custom, securely-built chart with references to images stored in Docker Hub or other private registries. DHI securely packages customized Helm charts that reference your repositories, wherever they are stored, by default.
To customize image references, an organization owner must mirror the DHI chart repository to your organization on Docker Hub.
You can create one chart customization per Helm chart repository. This is different from image customizations, where you can create multiple customizations per repository. If you need to make changes, you can edit your existing customization. Alternatively, you can mirror the same Helm chart repository again and add a new customization to the new mirror.
NoteYou can customize Docker Hardened Image charts like any other Helm chart using standard Helm tools and practices, such as a
values.yamlfile, outside of Docker Hub. The following instructions describe how to customize image references for the chart using the Docker Hub web interface.
To customize a Docker Hardened Image Helm chart after it has been mirrored:
Sign in to Docker Hub.
Select My Hub.
In the namespace drop-down, select your organization that has a mirrored DHI repository.
Select Hardened Images > Manage > Mirrored Helm charts.
For the mirrored DHI repository you want to customize, select the Name.
Select the Customizations tab.
Select Create customization.
At this point, the on-screen instructions will guide you through the customization process.
Helm chart customization YAML file
When using the CLI, Helm chart customizations use the same prepare / create
workflow as image customizations, but the configuration section uses
reference_mappings instead of image fields.
Use reference_mappings to substitute image references within the chart, for
example to point a chart's image references at your mirrored DHIs.
name: use mirrored images
targets:
- destination: my-org/dhi-haproxy-chart
tag_definition_id: haproxy/helm/1
reference_mappings:
- from: dhi/haproxy
to: my-org/dhi-haproxy| Field | Description |
|---|---|
reference_mappings[].from | The image reference in the chart to replace. |
reference_mappings[].to | The replacement image reference, typically a mirrored DHI in your organization. |
Monitor customization builds
After creating a customization, you can track build status and view logs through Docker Hub or the DHI CLI.
- Sign in to Docker Hub.
- Select My Hub.
- In the namespace drop-down, select your organization.
- Select Hardened Images > Manage.
- Select the Customizations tab.
List builds for a customization:
$ docker dhi customization build list <customization-id> --org my-org
Get details of a specific build:
$ docker dhi customization build get <customization-id> <build-id> --org my-org
View build logs:
$ docker dhi customization build logs <customization-id> <build-id> --org my-org
Edit or delete a customization
Sign in to Docker Hub.
Select My Hub.
In the namespace drop-down, select your organization that has a mirrored repository.
Select Hardened Images > Manage.
Select Customizations.
For the customized DHI repository you want to manage, select the menu icon in the far right column. From here, you can:
- Edit: Edit the customization.
- Create new: Create a new customization based on the source repository.
- Delete: Delete the customization.
Follow the on-screen instructions to complete the edit or deletion.
To edit a customization, update your YAML file and run:
$ docker dhi customization edit my-customization.yaml --org my-org
The YAML file must include the id field to identify which customization to
update. To find the ID, run docker dhi customization list --org my-org.
To delete a customization by ID:
$ docker dhi customization delete <id> --org my-org
$ docker dhi customization delete <id> --org my-org --force
The --force flag skips the confirmation prompt.
