Phase 3: Artifact migration

Importing Docker images

Container images do not need to be exported to a folder. A registry-to-registry tool such as crane copies an image directly from your existing registry into Cloudsmith, preserving its digest and every platform in a multi-architecture image. This is faster than pulling and pushing through a Docker daemon, needs no local disk, and works for OCI artifacts such as Helm charts too. Because of that, migrate container images first: they are usually the bulk of the bytes and the least work.

How it works

Existing registryCloudsmithcrane copy: manifests and layers stream registry to registryNo export, no local disk, digests preserved

Before you begin

  • Create the target repository.
  • Install crane.
  • Have credentials for the source registry and for Cloudsmith. Authenticate to Cloudsmith with your account name and an API key as the password.
  • Know the Cloudsmith image path: docker.cloudsmith.io/OWNER/REPOSITORY/IMAGE:TAG.

Note

If you use a custom domain for Docker, replace docker.cloudsmith.io with it throughout. Set the domain up before the migration so images are pushed to their final address.

Copy one image

Log in to both registries, then copy. Multi-architecture images are copied whole, with every platform:

shell
crane auth login registry.example.com --username source-user --password-stdin
crane auth login docker.cloudsmith.io --username my-user --password-stdin
crane copy \
  registry.example.com/team/my-image:1.0.0 \
  docker.cloudsmith.io/my-org/my-repo/my-image:1.0.0

crane also reads credentials from an existing docker login. See the crane copy reference for the full option list. If you already use skopeo, skopeo copy --all docker://SOURCE docker://DESTINATION does the same job; without --all it copies only the platform matching the machine it runs on.

Copy a whole repository

crane ls lists the tags of an image, so a loop over it migrates every version. Wrap it in a second loop over your image names to move a whole registry, logging any failure so the run can be repeated.

shell
for tag in $(crane ls registry.example.com/team/my-image); do
  crane copy "registry.example.com/team/my-image:$tag" "docker.cloudsmith.io/my-org/my-repo/my-image:$tag" ||
    echo "my-image:$tag" >> copy-failures.log
done

Where to get the image names depends on the source. crane catalog registry.example.com works for Nexus and most registries. Artifactory does not serve a top-level catalog; list each Docker repository through its own endpoint instead:

shell
jf rt curl -s -XGET /api/docker/docker-local/v2/_catalog

Alternatives

Docker CLI. If you cannot install crane, pull, retag, and push each image through the Docker daemon. This copies only the platform matching the machine you run it on.

shell
docker pull registry.example.com/team/my-image:1.0.0
docker tag registry.example.com/team/my-image:1.0.0 docker.cloudsmith.io/my-org/my-repo/my-image:1.0.0
docker push docker.cloudsmith.io/my-org/my-repo/my-image:1.0.0

Air-gapped export. Where the source registry cannot reach Cloudsmith and no machine can see both, save images to tarballs with docker save and upload them with the Cloudsmith CLI:

shell
docker save my-image:1.0.0 -o my-image-1.0.0.tar
cloudsmith push docker my-org/my-repo my-image-1.0.0.tar

Important

Images uploaded as tarballs get a different digest from the same image pushed through the registry protocol, so anything that pins by digest must be updated. Prefer a registry-to-registry copy where the network allows it.

Verify

Copied images keep their digests, so compare them directly:

shell
crane digest registry.example.com/team/my-image:1.0.0
crane digest docker.cloudsmith.io/my-org/my-repo/my-image:1.0.0

Then confirm nothing is stuck synchronizing:

shell
cloudsmith list packages my-org/my-repo -q 'format:docker status:failed'

Next steps

Point Docker clients and CI at the new registry with the instructions in Docker registry, and see Running a bulk import for verifying a large import.