Skip to content

Mirror the Kit images ​

Copy the Kit images and the Pinned image into your own registry, and make the cluster pull them from there.

An installed Kit builds none of its own images. The nodes pull the three Kit images, jr2-harness, jr2-operator and jr2-orchestrator, from ghcr.io/snapwich. They pull the Pinned image, the Envoy image of the Custodian, from docker.io. Mirror these four images when the nodes cannot reach those registries, or when the cluster pulls from one registry only.

jr2 up also checks each model that an Agent names, from a pod in the cluster. That pod uses the Harness Kit image and the Envoy image, so the nodes also pull the images of that pod from the mirror.

jr2 kit push copies the images. kitRegistry tells jr2 up where the nodes pull them from:

ts
import { defineConfig } from "@jr2/orchestrator";

export default defineConfig({
  git: {
    credentials: [{ match: "*", token: "JR2_GIT_TOKEN", sshKey: "jr2-git-ssh" }],
  },
  // The registry that holds the copy of the Kit images, such as registry.example.com/jr2.
  // When JR2_KIT_REGISTRY is not set, the cluster pulls them from ghcr.io/snapwich.
  kitRegistry: process.env.JR2_KIT_REGISTRY,
});

Before you start ​

  • An Instance, with its dependencies installed at the Kit version that you want to mirror.
  • Docker with Buildx on your computer. jr2 kit push uses docker buildx imagetools.
  • A registry that you can push to, and that the nodes can pull from. Log in to it with docker login. In the commands on this page, <registry> is the registry and its path, such as registry.example.com/jr2.
  • Your computer can pull from ghcr.io and docker.io.

Copy the images ​

Run jr2 kit push in the Instance folder:

sh
jr2 kit push <registry>
text
…
jr2 kit push — mirroring the v<version> kit images to <registry>
harness: copied ghcr.io/snapwich/jr2-harness:<version> → <registry>/jr2-harness:<version>
operator: copied ghcr.io/snapwich/jr2-operator:<version> → <registry>/jr2-operator:<version>
orchestrator: copied ghcr.io/snapwich/jr2-orchestrator:<version> → <registry>/jr2-orchestrator:<version>
custodian: copied docker.io/envoyproxy/envoy:<tag>@<digest> → <registry>/envoy:<tag>@<digest>
mirrored 4 image(s), 0 already present
{"registry":"<registry>","version":"<version>","images":{"harness":"<registry>/jr2-harness:<version>","operator":"<registry>/jr2-operator:<version>","orchestrator":"<registry>/jr2-orchestrator:<version>","custodian":"<registry>/envoy:<tag>@<digest>"}}

<version> is the Kit version. <tag> and <digest> are the tag and the digest of the Envoy image that this Kit version pins. The first line (…) is the .env line, when .env sets a variable that your shell does not set. The last line is on stdout. The other lines are on stderr.

jr2 kit push copies the images from registry to registry. It copies each platform of an image, with the same digests, and it does not put the images on your computer.

jr2 kit push does not read the Instance. In the Instance folder, the global jr2 runs the Instance's own @jr2/cli (Handoff), so the command copies the images of the Instance's Kit version. Outside an Instance, it copies the images of the version of your global jr2.

A version tag of jr2 never moves to different content. Thus jr2 kit push does not copy an image that is in the registry already. You can run it again at any time:

text
…
jr2 kit push — mirroring the v<version> kit images to <registry>
harness: already present — <registry>/jr2-harness:<version>
operator: already present — <registry>/jr2-operator:<version>
orchestrator: already present — <registry>/jr2-orchestrator:<version>
custodian: already present — <registry>/envoy:<tag>@<digest>
mirrored 0 image(s), 4 already present
…

Pull from the mirror ​

Set kitRegistry in jr2.config.ts, as in the example. The example reads it from .env. Add this line to .env:

text
JR2_KIT_REGISTRY=<registry>

Give kitRegistry the same value that you gave jr2 kit push, with no / at the end. The nodes then pull <registry>/jr2-harness:<version>, <registry>/jr2-operator:<version>, <registry>/jr2-orchestrator:<version> and <registry>/envoy:<tag>@<digest>.

jr2 version --local shows where the Kit images come from:

sh
jr2 version --local
text
→ .env: JR2_KIT_REGISTRY, …
cli:       <version>    <instance folder>/node_modules/@jr2/cli
global:    <global version>    <global folder>
kit:       <version>    <instance folder>/node_modules/@jr2/orchestrator  ok
instance:  my-instance  <instance folder>  (installed kit → <registry>)
node:      v24.18.0

<instance folder> is the path of your Instance folder. <global version> and <global folder> are the version and the folder of your global jr2, which runs the Instance's own @jr2/cli. node gives your version of Node.js.

Then converge:

sh
jr2 up
text
…
images: installed kit — the published v<version> Harness, operator and Orchestrator, pulled from <registry> (kitRegistry)
custodian image: <registry>/envoy:<tag>@<digest> (pinned, deployed — never built)
…
converged — `jr2 run <workflow>` when ready

Mirror each new Kit version ​

The mirror holds the images of the versions that you copied, and no others. jr2 up never pushes to kitRegistry. Thus, when you upgrade the Kit version, run jr2 kit push <registry> again before jr2 up. Run it in the Instance folder after you install the new version. See Upgrade the Kit version.

One mirror can serve each Instance on the cluster, and each cluster of your organization. It can hold the images of more than one Kit version.

kitRegistry is not registry. registry is where jr2 up pushes the images that it builds. kitRegistry is where the nodes pull the Kit images and the Pinned image. You can set one, the other, or both.

jr2 sets no image pull secret on its pods. The nodes must pull from the mirror with no pull secret.

Rules ​

  • jr2 kit push needs the registry:

    text
    jr2 kit push: no target registry
    usage: jr2 kit push <registry>
    …

    It exits with code 2.

  • push is the only subcommand of jr2 kit. jr2 kit refuses any other word with unknown kit subcommand: <word>, and exits with code 2. With no word, it prints jr2 kit: no subcommand, and exits with code 2.

  • When the image is not at its published place, jr2 kit push stops: error: <image>: <source> is not there, so nothing can be mirrored to <target>. <image> is harness, operator, orchestrator or custodian. <source> is its published reference, and <target> is its reference in the mirror. The next lines of the error say why. Check that <version> is a released Kit version.

  • When a copy fails, jr2 kit push stops, and exits with code 1. It gives error: Command failed: docker buildx imagetools create -t <target> <source>, then the lines of Docker. Check that docker login has logged you in to the registry, and that the registry is reachable.

The docs of Kit version 0.5.1. Each page is also at its .md URL.