
## Keep private registry in sync

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/mirror-images-to-private-registry

> Discover which Atlan images to mirror, replicate them to your private registry, and point the SDR Orchestrator at an image map in object storage

# Keep private registry in sync

:::warning Important!
Some capabilities shown here may require additional enablement or licensing. Contact your Atlan representative for details.
:::

:::tip New to mirroring?
Start with [Image procurement approach](https://docs.atlan.com/llms/platform/self-deployed-runtime/image-procurement/llms.txt) for *when* and *why* to mirror Atlan images and *which* approach to choose (public Docker Hub, a prefix rewrite, or an image map). This guide covers the **image-map implementation** for keeping a mirror in sync.
:::

If your environment blocks pulls from public registries, you mirror Atlan app images into your own private registry before the SDR Orchestrator can deploy or upgrade them. This guide describes the recommended flow to keep that mirror current:

1. **Poll** Atlan for the latest images your tenant needs.
2. **Mirror** any new images into your registry.
3. **Write an image map** back to your object storage that maps each Atlan source image to your mirrored image.
4. The SDR Orchestrator **reads the map** at install and upgrade time and pulls from your registry instead of the public source.

This works for both connector apps and the SDR Orchestrator's own image, and it doesn't require Atlan to know anything about your registry—you stay in control of what's mirrored and where it lives.

:::info When to use this
Use this flow if you mirror images and either (a) your registry changes the image repository or tag during replication, or (b) you want a machine-readable, pollable source of truth for which images to mirror. If you simply re-host images under a single prefix with identical names and tags, the simpler `containerRegistryBase` / `container_registry.base` prefix rewrite shown in the install guides is sufficient.
:::

## How it works

```
 Atlan (Global Marketplace) Your environment
 ┌──────────────────────────┐
 │ latest-releases endpoint │◀── 1. poll ──── your mirroring job
 └──────────────────────────┘ │
 2. pull + push │ (mirror images)
 ▼
 your private registry
 │
 3. write image map ▼
 ┌──────────────────────────┐
 │ object storage │
 │ sdr/image-map.yaml │
 └──────────────────────────┘
 ▲
 4. read on │
 install / │
 upgrade │
 SDR Orchestrator
```

## Prerequisites

- A working **SDR Orchestrator** installation. See [Install on Docker/Podman](https://docs.atlan.com/llms/platform/self-deployed-runtime/install-with-orchestrator/llms.txt) or [Install on Kubernetes](https://docs.atlan.com/llms/platform/self-deployed-runtime/install-orchestrator-on-kubernetes/llms.txt).
- An **Atlan API token** for your tenant (used to poll the latest-releases endpoint). See [Manage API tokens](https://docs.atlan.com/llms/governance/stewardship/manage-api-tokens/llms.txt).
- Write access to the **same object storage** bucket the SDR is configured to use (the `objectstore` component in your `config.yaml` / `values.yaml`).
- Your private registry credentials, and a host that can reach both the Atlan source registry (to pull) and your registry (to push).

## Step 1: Discover images to mirror

Poll the latest-releases endpoint for your tenant. It returns the source image reference for every app your tenant can run that's eligible for Self-Deployed Runtime, plus the SDR Orchestrator image itself.

```bash
curl -sS \
 -H "Authorization: Bearer $ATLAN_API_TOKEN" \
 "https://<your-tenant>.atlan.com/api/service/marketplace/latest-releases"
```

The response lists each image as a `repo:tag` reference under `image`:

```json
{
 "releases": [
 {
 "app_id": "019aaaaa-0000-7000-8000-000000000001",
 "app_name": "teradata",
 "version": "main-cfbc9da",
 "version_id": "019b2b7d-...",
 "image": "atlanhq/atlan-teradata-app:main-cfbc9da"
 },
 {
 "app_id": "019d480a-25b6-7051-8596-6ce892530197",
 "app_name": "sdr-orchestrator-k8s",
 "version": "main-3c1883c",
 "version_id": "019cffff-...",
 "image": "atlanhq/atlan-sdr-orchestrator-k8s:main-3c1883c"
 }
 ]
}
```

Compare this list with what you've already mirrored to find what's new. The `image` field is the **Atlan source reference**—what you pull *from*.

## Step 2: Mirror new images to your registry

For each image returned in Step 1 that you don't already have, pull it from the Atlan source and push it to your registry. For example:

```bash

# Pull the source image (requires the Docker Hub PAT from your Atlan representative)

docker pull atlanhq/atlan-teradata-app:main-cfbc9da

# Tag and push to your registry

docker tag atlanhq/atlan-teradata-app:main-cfbc9da \
 registry.mycompany.com/atlan/atlan-teradata-app:main-cfbc9da
docker push registry.mycompany.com/atlan/atlan-teradata-app:main-cfbc9da
```

You may keep the same repository name and tag, or rename either during replication—the image map in the next step records whatever mapping you choose.

:::tip Verify before you mirror
Atlan signs every image with keyless Cosign. Verify the signature before pushing it into your registry—see [Verify container images](https://docs.atlan.com/llms/platform/self-deployed-runtime/verify-container-images/llms.txt).
:::

## Step 3: Write image map to object storage

Write a YAML file to your object storage that maps each Atlan source image to its mirrored location. Upload it to the same bucket the SDR uses (for example, at the key `sdr/image-map.yaml`).

```yaml title="sdr/image-map.yaml"
images:
 # Quote keys and values — they contain colons.
 # repo -> repo: covers every tag of this image; the source tag is preserved.
 "atlanhq/atlan-teradata-app": "registry.mycompany.com/atlan/atlan-teradata-app"
 "atlanhq/atlan-sdr-orchestrator-k8s": "registry.mycompany.com/atlan/atlan-sdr-orchestrator-k8s"

 # repo:tag -> repo:tag: pins a single image when you renamed the repo OR the
 # tag during replication.
 "atlanhq/atlan-teradata-app:main-cfbc9da": "registry.mycompany.com/atlan/teradata:main-cfbc9da-approved"
```

How a source image is resolved:

- An exact `repo:tag` entry wins, and its value is used verbatim—so you can change the repository **and** the tag during replication.
- Otherwise a bare `repo` entry is used, and the source tag is appended unchanged—one entry covers every version of that app.
- If an image isn't found in the map, the SDR leaves the reference unchanged (the pull then fails with your blocked source, which surfaces the gap).

:::note Externally managed Kubernetes releases (optional)
If the SDR Orchestrator's own Helm release is managed by an external tool (for example, Flux) under a name or namespace that differs from the default, add an optional `release` block so self-update targets the right release:

```yaml
release:
 name: my-sdr-release # overrides the default atlan-sdr-<deployment_name>
 storage_namespace: flux-system # namespace holding the Helm release record
```
:::

## Step 4: Point SDR Orchestrator at map

Tell the SDR where the map lives in object storage. The path is a **key within the object storage bucket** already configured for the SDR—the SDR reads it through the same `objectstore` component.

### Docker / Podman

Add `image_map_path` to the `container_registry` section of `config.yaml`:

```yaml title="config.yaml"
container_registry:
 image_map_path: "sdr/image-map.yaml"
 # username/password are still used for the pull secret if your registry needs auth
 username: "<your-registry-username>"
 password: "<your-registry-token>"
```

Restart the orchestrator to pick up the config change:

```bash
docker compose up -d
```

### Kubernetes

Set `imageMapPath` under `sdr.config` in `values.yaml`:

```yaml title="values.yaml"
sdr:
 config:
 imageMapPath: "sdr/image-map.yaml"
```

Apply the change:

```bash
helm upgrade atlan-sdr- ./chart \
 --namespace atlan \
 -f values.yaml
```

When `image_map_path` is set, it takes precedence over the `containerRegistryBase` / `container_registry.base` prefix rewrite.

## How the SDR uses the map

The SDR Orchestrator reads the image map from object storage **on every install and upgrade**, including its own self-update. It resolves each image through the map before pulling, so:

- **Connector installs and upgrades** pull from your registry.
- **SDR self-updates** pull the orchestrator image from your registry.

Because the SDR reads the map fresh each time, you don't need to restart or reconfigure the SDR when you mirror a new image—just update the map in object storage and the next install or upgrade picks it up.

## Automate the refresh

Run Steps 1–3 on a schedule (for example, a cron job or CI pipeline) so newly published images are mirrored and recorded in the map before the SDR's hourly reconcile attempts an upgrade. A typical job:

1. Poll `latest-releases`.
2. Compare with the entries already in your `image-map.yaml`.
3. For anything new: verify, pull, push, and add the mapping.
4. Upload the updated `image-map.yaml` to object storage.

## See also

- [Install SDR Orchestrator on Docker/Podman](https://docs.atlan.com/llms/platform/self-deployed-runtime/install-with-orchestrator/llms.txt): includes the simpler `container_registry.base` prefix rewrite.
- [Install SDR Orchestrator on Kubernetes](https://docs.atlan.com/llms/platform/self-deployed-runtime/install-orchestrator-on-kubernetes/llms.txt): includes the `containerRegistryBase` prefix rewrite.
- [Verify container images](https://docs.atlan.com/llms/platform/self-deployed-runtime/verify-container-images/llms.txt): verify image signatures with Cosign before mirroring.
- [Configure network security](https://docs.atlan.com/llms/platform/self-deployed-runtime/configure-network-security/llms.txt): outbound connectivity requirements.

---
