shdctl artifact command
Mirror Docker images and ORAS artifacts between registries, and verify the result
読み終わるまでの所要時間 10 分最終更新 2日前
Before you deploy, sync artifacts from the source registry () to the target registry (). Set in the manifest: lists a default for it, but every sync subcommand — the pull-straight case below included — fails with when it is left out. Use one of these subcommands for the artifact type:
artifactSync.sourceRepositoryconfiguration.kubernetes.docker.repositoryartifactSync.sourceRepositoryshdctl manifest schemasource registry is required- — Docker container images (uses
shdctl artifact sync images/docker pull/tag)push - — ORAS artifacts (registry-to-registry copy via
shdctl artifact sync oras)oras-go
The manifest's is used to prefix image paths on the target registry when set.
docker.namespaceTo pull straight from Unity's registry rather than mirror, set to the source registry and leave out. Every sync subcommand, included, then logs that there is nothing to mirror and exits 0 without contacting either registry — as it does whenever names the source. The manifest schema refuses a namespace there — every command that reads the manifest, , and among them, fails naming the field — because generation prefixes every image reference with it whatever the registry, and nothing mirrors images to that path, so the deploy could not pull them. Keep the block itself: without it every sync subcommand fails, and generation renders image references with no registry at all.
configuration.kubernetes.docker.repositorydocker.namespaceverify--target-registrymanifest validaterelease generateartifact syncdockersync orassync imagessync orassync imagesThe manifest names those images; does not. An app and the image it runs therefore reach your registry together, instead of the app arriving alone and failing the first time it runs. A release whose manifest names no images syncs only what lists.
versions.yamlversions.yamlTo expand the list, both subcommands read the manifest from the source registry. They contact it even when you pass .
--dry-runTwo further subcommands check a sync rather than perform one: proves your credentials work by syncing one artifact of each kind, and compares what your target registry holds against what your manifest requires without writing to it.
shdctl artifact sync preflightshdctl artifact sync verifyAll four subcommands (, , , ) accept:
imagesoraspreflightverify- : Skip shdctl version compatibility check against the release package
--skip-version-check
Preflight
Verify your Docker and ORAS credentials are working before you run a full sync:
shdctl artifact sync preflight
The command picks one Docker image and one ORAS artifact from the release and attempts to sync them — a real copy into your registry, not a simulation. The image can be any in the release, whether or not your manifest enables the feature that needs it, and its local copy is removed once the push succeeds. A successful run confirms pull/push credentials. On failure, the command prints troubleshooting hints, such as expired tokens or a missing .
docker loginOptions:
- : Target registry URL (defaults to manifest value)
--target-registry - : Path to extracted release (defaults to
--extracted-release)./extracted-release
preflightverifySync Docker images
-
Authenticate to both source and target registries before you sync:docker login <source-registry>docker login <target-registry>
-
Preview the commands that would be executed:shdctl artifact sync images --dry-run
-
Run the sync:shdctl artifact sync images
Each image is pulled as (), so your registry receives a single-platform amd64 image under each tag, whatever the source holds.
linux/amd64docker pull --platform linux/amd64What gets mirrored
The mirror is scoped to your manifest: an image that only a feature you have turned off needs is not copied. Five features gate images this way, each read from one manifest field:
Images | Mirrored when |
|---|---|
| Istio (istiod, proxy, ztunnel, CNI) | |
| Prometheus and Grafana | |
| Log collection (Loki, Alloy) | |
| Database monitoring (the PMM server) | |
| The in-cluster object store (garage and its bootstrap job) | |
Every other image in the release is mirrored on every run — including , the sidecar both database charts pin whether or not database monitoring is enabled, so expect it in a monitoring-off registry.
percona/pmm-clientA run that skips anything reports what it left out. The summary goes to stderr, so it never lands in the middle of the command list a writes to stdout. For a manifest with Istio, Prometheus, log collection, and database monitoring off, which keeps the in-cluster object store:
--dry-runMirroring 91 of 112 versions.yaml entries. Skipped 21: dbMonitoring 1 istio 4 logCollection 6 logCollection,prometheus 1 prometheus 9Run with --all to mirror every image in the release.
Each row names a feature — or, where an image serves more than one, the set of features of which none is enabled — and counts the entries skipped under it. The header counts entries rather than images because two entries can name the same reference; the de-duplicated image count is logged separately. Nothing is printed when nothing was skipped.
versions.yamlPass to mirror the release's full image set regardless of what your manifest enables. Use it for a registry shared by deployments with different feature sets, or to keep the option of turning a feature on later without going back to Unity's registry for its images.
--allOtherwise, turning a feature on means re-running : the images it needs were never mirrored, and a deploy cannot pull what is not there. reports exactly which images a registry is missing.
shdctl artifact sync imagesshdctl artifact sync verifyOptions:
- : Show commands without executing (default: false)
--dry-run - : Mirror every image in the release, ignoring which features the manifest enables (default: false)
--all - : Target registry URL (defaults to manifest value)
--target-registry - : Path to extracted release (defaults to
--extracted-release)./extracted-release - : Sync only images whose target repository (
--name) contains this string, or whose full target reference — as<target-registry>/<namespace>/<path>lists it — equals it. A string that matches nothing syncs nothing and exits 0verify - : Remove local images (
--cleanup) after each push (default: false)docker rmi - : Skip images already present on the target registry, checked with
--skip-existing(default: false)docker manifest inspect - : Number of images to sync in parallel. When the flag is omitted, the manifest's
--concurrencyapplies if it is set, andartifactSync.concurrency(sequential) otherwise.1lists a default ofshdctl manifest schemafor that field, but a field you leave out is not filled in — set it to sync in parallel.5
Example for CI: skip existing, cleanup disk.
shdctl artifact sync images --skip-existing --cleanup
Sync ORAS artifacts
ORAS artifact sync reads authentication from Docker's credential store () automatically. Run for both source and target registries before you sync.
~/.docker/config.jsondocker loginshdctl artifact sync oras --dry-run
This prints each copy as the equivalent command. The real run copies in-process, so the CLI is not needed.
oras copy <source> <target>orasshdctl artifact sync oras
Options:
- : Show commands without executing (default: false)
--dry-run - : Target registry URL (defaults to manifest value)
--target-registry - : Path to extracted release (defaults to
--extracted-release)./extracted-release - : Sync only ORAS artifacts whose name or target reference contains this string. A string that matches nothing syncs nothing and exits 0
--name - : Number of artifacts to sync in parallel. When the flag is omitted, the manifest's
--concurrencyapplies if it is set, andartifactSync.concurrency(sequential) otherwise — as for1, the schema's listed default ofsync imagesis not applied.5
Verify the target registry
Compare what your target registry holds against what your manifest requires. Authenticate to the target registry first ():
docker login <target-registry>shdctl artifact sync verify
It probes the target registry for every image in the release — including the ones the release manifest names, which mirrors — and reports:
sync images- required and present — a count.
- required and MISSING — listed one per line. A deploy cannot pull these, so the command exits non-zero and a CI pipeline can gate a deploy on it. Mirror them with .
shdctl artifact sync images - present but not required by this manifest — listed one per line. Not a failure, and nothing to fix: the residue of an earlier run, of a feature you have since turned off, or of
--all, which copies one image drawn from the whole release. Sync never deletes, so removing them is a registry-side operation.preflight - release manifests this target could not answer for — listed one per line. The images they name went unchecked, so the command exits non-zero rather than call the registry clean. Mirror them with .
shdctl artifact sync oras
It reads those manifests from the target registry, not the source, so this command needs nothing from Unity's registry and works on an air-gapped site. Run it after , which is what copies them there.
shdctl artifact sync orasCounts are unique image references after de-duplication rather than entries — two entries can name the same image. The command only reads the registry: it writes nothing and deletes nothing.
versions.yamlOptions:
- : Target registry URL (defaults to manifest value)
--target-registry - : Path to extracted release (defaults to
--extracted-release)./extracted-release - : Number of images to probe in parallel. When the flag is omitted, the manifest's
--concurrencyapplies if it is set, as it does for the other sync subcommands, andartifactSync.concurrencyotherwise — higher than4because a probe is a metadata read, costing no disk and no image transfer.sync images
Two things to know before acting on a report:
Everything missing usually means credentials, not an empty registry. The probe is a , which cannot tell "not found" from "not authorized", so an absent or expired registry credential reads exactly like a registry holding nothing and would send you off to re-mirror images you already have. When every required image comes back missing and nothing extraneous was found, says so and points at . That is the runbook order: proves the credentials, then reports the content.
docker manifest inspectverifypreflightshdctl artifact sync preflightshdctl artifact sync verifyThe "present but not required" list is not a full audit of your registry. It covers only the images this release defines: a probe asks about one reference at a time and cannot enumerate a registry. Tags left behind by earlier releases are not reported, so an empty list means "nothing this release defines is here unnecessarily", not "this registry is clean".
Full sync example with ECR
ECR creates a repository on push only where a repository creation template covers its path. With the AWS baseline example in the release package (), set to its output, the prefix its template covers.
extracted-release/platform/shd/aws-baseline-example/configuration.kubernetes.docker.namespaceecr_repository_prefix# Authenticate to both registries (Docker prompts for the password)aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin <account>.dkr.ecr.us-east-1.amazonaws.comdocker login -u <user> uccmpprivatecloud.azurecr.io# Preflight: verify authentication worksshdctl artifact sync preflight# Sync Docker images (only those your manifest's enabled features require)shdctl artifact sync images --skip-existing --cleanup# Sync ORAS artifacts (reads Docker credential store automatically)shdctl artifact sync oras# Confirm the registry now holds every image the manifest requiresshdctl artifact sync verify
In automated environments, pipe the password from a secret store with instead of passing on the command line. The flag writes the password to your shell history and to the process list (visible to ), and Docker prints when you use it.
--password-stdin-p <password>-pps auxWARNING! Using --password via the CLI is insecure