Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 143 additions & 37 deletions content/manuals/dhi/how-to/mirror.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,54 +124,160 @@

## Mirror from Docker Hub to another registry

> [!IMPORTANT]
>
> To continue receiving image updates and preserve access to Docker Hardened
> Images, ensure that any copies pushed to other registries remain private.

After you've mirrored a Docker Hardened Image repository to your organization's
namespace on Docker Hub, you can optionally mirror it to another container
registry, such as Amazon ECR, Google Artifact Registry, GitHub Container
Registry, or a private Harbor instance.

You can use any standard workflow, including:

- [The Docker CLI](/reference/cli/docker/_index.md)
- [The Docker Hub Registry API](/reference/api/registry/latest/)
- Third-party registry tools or CI/CD automation
You can use any standard workflow to mirror the image, such as the
[Docker CLI](/reference/cli/docker/_index.md), [Docker Hub Registry
API](/reference/api/registry/latest/), third-party registry tools, or CI/CD
automation.

However, to preserve the full security context, including attestations, you must
also mirror its associated OCI artifacts. Docker Hardened Images store the image
layers on Docker Hub (`docker.io`) and the signed attestations in a separate
registry (`registry.scout.docker.com`).

To copy both, you can use [`regctl`](https://regclient.org/cli/regctl/), an
OCI-aware CLI that supports mirroring images along with attached artifacts such
as SBOMs, vulnerability reports, and SLSA provenance. For ongoing synchronization,
you can use [`regsync`](https://regclient.org/cli/regsync/).

### Example mirroring with `regctl`

The following example shows how to mirror a specific tag of a Docker Hardened
Image from Docker Hub to another registry, along with its associated
attestations using `regctl`. You must [install
`regctl`](https://github.com/regclient/regclient) first.

1. Set environment variables for your specific environment. Replace the
placeholders with your actual values.

```console
$ export DOCKER_USERNAME="YOUR_DOCKER_USERNAME"
$ export DOCKER_PAT="YOUR_DOCKER_PAT"
$ export DEST_REG="registry.example.com"
$ export DEST_REPO="mirror/dhi-python"
$ export SRC_REPO="docker.io/<your-org>/dhi-python"
$ export SRC_TAG="3.13-alpine3.21"
```

2. Sign in via regctl to Docker Hub, the Scout registry that contains
the attestations, and your destination registry.

```console
$ regctl registry login -u "$DOCKER_USERNAME" --pass-stdin docker.io

Check failure on line 175 in content/manuals/dhi/how-to/mirror.md

View workflow job for this annotation

GitHub Actions / validate (vale)

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'regctl'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'regctl'?", "location": {"path": "content/manuals/dhi/how-to/mirror.md", "range": {"start": {"line": 175, "column": 16}}}, "severity": "ERROR"}
$ regctl registry login -u "$DOCKER_USERNAME" --pass-stdin registry.scout.docker.com
$ regctl registry login "$DEST_REG
```

3. Mirror the image by digest from Docker Hub to your destination registry.

First, get a digest for a specific tag and platform. For example, `linux/amd64`.

```console
DIGEST="$(regctl manifest head "${SRC_REPO}:${SRC_TAG}" --platform linux/amd64)"
```

Then, copy the image by digest to ensure you get the exact same image.

```console
regctl image copy \
"${SRC_REPO}@${DIGEST}" \
"${DEST_REG}/${DEST_REPO}@${DIGEST}"
```

4. Mirror the attestations from the Scout registry to your target registry using
`--referrers` and referrer endpoints:

```console
$ regctl image copy \
--referrers \
--referrers-src "registry.scout.docker.com/<your-org>/dhi-python" \
--referrers-tgt "${DEST_REG}/${DEST_REPO}" \
"registry.scout.docker.com/<your-org>/dhi-python@${DIGEST}" \
"${DEST_REG}/${DEST_REPO}@${DIGEST}"
```

5. Verify that artifacts were preserved.

List attached artifacts (SBOM, provenance, VEX, vulnerability reports).

```console
$ regctl artifact list "${DEST_REG}/${DEST_REPO}@${DIGEST}"
```

If you use Docker Scout:

```console
$ docker scout attest list "registry://${DEST_REG}/${DEST_REPO}@${DIGEST}"
```

### Example ongoing mirroring with `regsync`

`regsync` automates pulling from your organizations mirrored DHI repositories on
Docker Hub and pushing to your external registry including attestations. It
reads a YAML configuration file and can filter tags.

The following example uses a `regsync.yaml` file that syncs Node 24 and Python
3.12 Debian 13 variants, excluding Alpine and Debian 12.

```yaml{title="regsync.yaml"}
version: 1
# Optional: inline creds if not relying on prior CLI logins
# creds:
# - registry: docker.io
# user: <your-docker-username>
# pass: "{{file \"/run/secrets/docker_token\"}}"
# - registry: registry.scout.docker.com
# user: <your-docker-username>
# pass: "{{file \"/run/secrets/docker_token\"}}"
# - registry: registry.example.com
# user: <service-user>
# pass: "{{file \"/run/secrets/dest_token\"}}"

sync:
- source: docker.io/<your-org>/dhi-node
target: registry.example.com/mirror/dhi-node
type: repository
fastCopy: true
referrers: true
referrerSource: registry.scout.docker.com/<your-org>/dhi-node
referrerTarget: registry.example.com/mirror/dhi-node
tags:
allow: [ "24.*" ]
deny: [ ".*alpine.*", ".*debian12.*" ]

- source: docker.io/<your-org>/dhi-python
target: registry.example.com/mirror/dhi-python
type: repository
fastCopy: true
referrers: true
referrerSource: registry.scout.docker.com/<your-org>/dhi-python
referrerTarget: registry.example.com/mirror/dhi-python
tags:
allow: [ "3.12.*" ]
deny: [ ".*alpine.*", ".*debian12.*" ]
```

The following example shows how to use the Docker CLI to pull a mirrored DHI and
push it to another registry:
To do a dry run with the configuration file, you can run the following command.
You must [install `regsync`](https://github.com/regclient/regclient) first.

```console
# Authenticate to Docker Hub (if not already signed in)
$ docker login

# Pull the image from your organization's namespace on Docker Hub
$ docker pull <your-namespace>/dhi-<image>:<tag>

# Tag the image for your destination registry
$ docker tag <your-namespace>/dhi-<image>:<tag> registry.example.com/my-project/<image>:<tag>

# Push the image to the destination registry
# You will need to authenticate to the third-party registry before pushing
$ docker push registry.example.com/my-project/<image>:<tag>
$ regsync check -c regsync.yaml
```

> [!IMPORTANT]
>
> To continue receiving image updates and preserve access to Docker Hardened
> Images, ensure that any copies pushed to other registries remain private.

### Include attestations when mirroring images
To run the sync with the configuration file:

Docker Hardened Images are signed and include associated attestations that
provide metadata such as build provenance and vulnerability scan results. These
attestations are stored as OCI artifacts and are not included by default when
using the Docker CLI to mirror images.

To preserve the full security context when copying DHIs to another registry, you
must explicitly include the attestations. One tool is `regctl`, which supports
copying both images and their associated artifacts.

For more details on how to use `regctl` to copy images and their associated
artifacts, see the [regclient
documentation](https://regclient.org/cli/regctl/image/copy/).
```console
$ regsync once -c regsync.yaml
```

## What's next

Expand Down
Loading