Skip to content
Open
Show file tree
Hide file tree
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
212 changes: 212 additions & 0 deletions embedded-cluster/embedded-image-template-functions.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# Image Template Functions for Embedded Cluster (Beta)

This topic describes how to use image template functions in Embedded Cluster v3 Helm extension values and in the KOTS HelmChart custom resource. These functions ensure that image references resolve correctly in both online and air gap installations.

For information about Embedded Cluster extensions, see [extensions](embedded-config#extensions) in _Embedded Cluster Config_. For information about the HelmChart custom resource, see [HelmChart v2](/reference/custom-resource-helmchart-v2).

## Overview

Image template functions automatically rewrite image references based on the installation mode:

- **Online**: Images are served through the Replicated proxy registry (`proxy.replicated.com` or your custom domain). Images that do not need to go through the proxy can be left unchanged using the `noProxy` parameter.
- **Air gap**: All images are rewritten to the local registry regardless of the `noProxy` parameter.

## Recommended Setup

Replicated recommends setting your chart's `values.yaml` image defaults to point to the Replicated proxy registry for all private and third-party images. This ensures the chart works out of the box when installed with `helm install` in online environments.

The proxy registry URL follows this format: `DOMAIN/proxy/APP_SLUG/UPSTREAM_REGISTRY/IMAGE_PATH`

Where:
- `DOMAIN` is `proxy.replicated.com` or your [custom domain](/vendor/custom-domains).
- `APP_SLUG` is the unique slug of your application.
- `UPSTREAM_REGISTRY/IMAGE_PATH` is the full upstream image path (for example, `ghcr.io/my-org/my-image` or `docker.io/bitnami/postgresql`).

### Charts with separate registry and repository fields

If a chart splits image references into separate `registry` and `repository` fields, set the proxy defaults in `values.yaml` and use `ReplicatedImageRegistry` and `ReplicatedImageRepository` in the HelmChart CR:

```yaml
# values.yaml
image:
registry: proxy.replicated.com
repository: proxy/my-app/ghcr.io/my-org/my-image
tag: v1.0.0
```

```yaml
# helmchart.yaml
apiVersion: kots.io/v1beta2
kind: HelmChart
spec:
values:
image:
registry: '{{repl ReplicatedImageRegistry (HelmValue ".image.registry") }}'
repository: '{{repl ReplicatedImageRepository (HelmValue ".image.repository") true }}'
```

`ReplicatedImageRegistry` omits `noProxy` so the function returns the correct proxy domain for the installation, including any [custom domain](/vendor/custom-domains) configuration. `ReplicatedImageRepository` sets `noProxy` to `true` because the repository value in `values.yaml` already contains the proxy path prefix (`proxy/my-app/...`). In air gap mode, both functions rewrite to the local registry regardless of `noProxy`.

### Charts with a single image field

If a chart expects the full image reference in a single field, set the proxy URL as the default in `values.yaml` and use `ReplicatedImageName` with `noProxy` set to `true`:

```yaml
# values.yaml
initImage: proxy.replicated.com/proxy/my-app/docker.io/library/busybox:1.36
```

```yaml
# helmchart.yaml
values:
initImage: '{{repl ReplicatedImageName (HelmValue ".initImage") true }}'
```

## Additional Use Cases

### Public images

If an image is public and does not need to go through the proxy registry, set the upstream reference directly in `values.yaml` and use `noProxy` so the reference is left unchanged in online mode but still rewritten for air gap:

```yaml
# values.yaml
publicImage: docker.io/library/busybox:1.36
```

```yaml
# helmchart.yaml
values:
publicImage: '{{repl ReplicatedImageName (HelmValue ".publicImage") true }}'
```

### Subchart images

If your chart includes subcharts that have their own `image.registry` and `image.repository` fields, apply the same pattern for each subchart. Set the proxy defaults under the subchart key in `values.yaml`:

```yaml
# values.yaml
my-subchart:
image:
registry: proxy.replicated.com
repository: proxy/my-app/docker.io/some-org/some-image
tag: "1.0.0"
```

```yaml
# helmchart.yaml
values:
my-subchart:
image:
registry: '{{repl ReplicatedImageRegistry (HelmValue ".my-subchart.image.registry") }}'
repository: '{{repl ReplicatedImageRepository (HelmValue ".my-subchart.image.repository") true }}'
```

### Embedded Cluster extension images

For Helm extensions in the [Embedded Cluster Config](embedded-config), the approach depends on whether you control the chart's `values.yaml`.

#### Your own charts

For charts you own, you can set the proxy defaults in `values.yaml` and use the same `HelmValue` with `noProxy` pattern described in [Recommended Setup](#recommended-setup).

#### Third-party charts

For third-party charts where you cannot modify `values.yaml` to set proxy defaults, provide the upstream image references directly in the extension values and omit `noProxy`. The template functions will add the proxy prefix in online mode and rewrite to the local registry in air gap mode.

If the chart uses separate registry and repository fields:

```yaml
# embedded-cluster.yaml
extensions:
helmCharts:
- chart:
name: ingress-nginx
chartVersion: "4.11.3"
releaseName: ingress-nginx
namespace: ingress-nginx
values: |
controller:
image:
registry: 'repl{{ ReplicatedImageRegistry "registry.k8s.io" }}'
repository: 'repl{{ ReplicatedImageRepository "registry.k8s.io/ingress-nginx/controller" }}'
```

**Note:** `ReplicatedImageRepository` requires the full upstream image path including the registry (for example, `registry.k8s.io/ingress-nginx/controller`), not just the repository portion.

If the chart uses a single image field:

```yaml
values: |
image:
repository: 'repl{{ ReplicatedImageName "docker.io/some-org/some-image" }}'
```

## Tips

- When referencing Docker Hub images through the Replicated proxy registry, use the full path including `docker.io` and the namespace. For official images, this means including `library`. For example, to proxy the `nginx` image, use `proxy.replicated.com/proxy/my-app/docker.io/library/nginx` (not `proxy.replicated.com/proxy/my-app/nginx`). For other Docker Hub images, include the organization (for example, `proxy.replicated.com/proxy/my-app/docker.io/bitnami/postgresql`).

## Function Reference

### ReplicatedImageName

```go
func ReplicatedImageName(image string, noProxy ...bool) string
```

Returns a full image reference (registry + repository + tag). Use this when a chart expects the entire image reference in a single field. The optional `noProxy` parameter, when set to `true`, leaves the image unchanged in online mode.

| Mode | noProxy | Result |
|------|---------|--------|
| Online | omitted | `proxy.replicated.com/proxy/<app-slug>/<image>` |
| Online | `true` | `<image>` (unchanged) |
| Air gap | any | `<local-registry>/<app-slug>/<name>:<tag>` |

### ReplicatedImageRegistry

```go
func ReplicatedImageRegistry(registry string, noProxy ...bool) string
```

Returns the registry host. Use this when a chart splits the image reference into separate `registry` and `repository` fields. The optional `noProxy` parameter, when set to `true`, returns the input registry unchanged in online mode.

| Mode | noProxy | Result |
|------|---------|--------|
| Online | omitted | `proxy.replicated.com` (or custom domain) |
| Online | `true` | `<registry>` (unchanged) |
| Air gap | any | `<local-registry-address>` |

### ReplicatedImageRepository

```go
func ReplicatedImageRepository(repository string, noProxy ...bool) string
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its awkward reading go code here. its not obvious that noProxy is optional or what the intention of the ... is

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, updating. ty

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this matches our docs elsewhere for template functions...

```

Returns the repository path. Use this together with `ReplicatedImageRegistry`. The optional `noProxy` parameter, when set to `true`, returns the input repository unchanged in online mode.

| Mode | noProxy | Result |
|------|---------|--------|
| Online | omitted | `proxy/<app-slug>/<repository>` |
| Online | `true` | `<repository>` (unchanged) |
| Air gap | any | `<app-slug>/<name>` |

### HelmValue

```go
func HelmValue(path string) string
```

Returns the value from the chart's `values.yaml` at the given dotted path. Use this to read the chart's default image values and pass them to image template functions.

## KOTS-Compatible Aliases

For backward compatibility with KOTS, the following template functions are available as aliases:

| KOTS function | Equivalent |
|--------------|------------|
| `LocalImageName` | `ReplicatedImageName` |
| `HasLocalRegistry` | Returns `true` in air gap mode |
| `LocalRegistryHost` | Returns the local registry address |
| `LocalRegistryNamespace` | Returns the app slug |
| `LocalRegistryAddress` | Returns `<host>/<namespace>` |

For new configurations, use the `Replicated*` functions.
1 change: 1 addition & 0 deletions sidebarEmbeddedCluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = {
"embedded-v3-migrate",
"embedded-using",
"embedded-config",
"embedded-image-template-functions",
{

type: "category",
Expand Down