Poma
Poma

Reputation: 8474

How to add tag alias on docker hub without pulling an image

When I build image in CI I push it with a unique SHA tag. Then when I deploy it to production I want to change :latest alias to point to the same image like so:

docker pull org/foo:34f8a342
docker tag org/foo:34f8a342 org/foo:latest
docker push org/foo:latest

Now I want to avoid pulling this image. The problem is that container for deploy script is different from container that was used to build it so I don't have this image locally. Is there any way to add a tag alias on docker hub without the need to have this image locally?

Upvotes: 21

Views: 10579

Answers (5)

andr
andr

Reputation: 16044

tl;dr

docker buildx imagetools create --tag new-tag existing-tag

notes

Order of the arguments matters and this requires Docker Buildx. However, quoting the docs:

As of Docker Engine 23.0 and Docker Desktop 4.19, Buildx is the default build client.
(...)
Docker Buildx is installed by default with Docker Desktop. Docker Engine version 23.0 and later requires that you install Buildx from a separate package. Buildx is included in the Docker Engine installation instructions.

And so, in many distributions docker 23+ package installs buildx automatically. You can check if you have buildx already with:

docker buildx version

longer explanation

docker manifest create didn't work for me in case of multi-manifest images, e.g. multi-platform or with attestation. Below is a sanitized example with parts of manifest JSON skipped for readability:

$ docker manifest create new-tag existing-tag
Error: existing-tag is a manifest list

$ docker manifest inspect -v existing-tag
[
  {
    "Ref": "existing-tag@sha256:abc",
    "Descriptor": {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    "OCIManifest": {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "layers": [
        {
          "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
          ...
        },
        ... other image layers go here ...
      ]
    }
  },
  {
    "Ref": "existing-tag@sha256:xyz",
    "Descriptor": {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "platform": {
        "architecture": "unknown",
        "os": "unknown"
      }
    },
    "OCIManifest": {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "layers": [
        {
          "mediaType": "application/vnd.in-toto+json",
          ...
        }
      ]
    }
  }
]

As you can see the tag points to a manifest list with first being a docker image consisting of layers, while the second is an attestation manifest. This seems to break the docker manifest create command.


What worked well for me in this case is using the newer docker buildx imagetools create command like so:

$ docker buildx imagetools create --tag new-tag existing-tag
[+] Building 1.6s (1/1) FINISHED                                                                                                                                                                                     
 => [internal] pushing new-tag

... which seems to play well with multi-manifest images. Specifically, docker manifest inspect -v new-tag showed the same output as docker manifest inspect -v existing-tag

Upvotes: 1

Thiago
Thiago

Reputation: 997

In my case, I had to add an extra tag to an existing multi arch image. Docker tag would not work, because it would pull and tag only the image matching my OS.

I didn't want to use docker buildx imagetools create again because it would create a new imageIndex.

I used Skopeo copy command.

skopeo --multi-arch=index-only copy docker://<IMAGE>:<TAG> docker://<IMAGE>:<NEW TAG>

Upvotes: 0

mabraham
mabraham

Reputation: 3016

Using the experimental docker manifest command:

docker manifest create $REPOSITORY:$TAG_NEW $REPOSITORY:$TAG_OLD
docker manifest push $REPOSITORY:$TAG_NEW

For a private registry, you may need to prepend $REGISTRY/ to the repository.

Upvotes: 21

Angel Tabares
Angel Tabares

Reputation: 343

As it can be seen here its not allowed, but if the problem is that pulling the entire image is slow as someone mentions in the comments it can be acheived faster just "pulling" the manifest as here through the Docker Registry API

MANIFEST=$(curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" "${REGISTRY_NAME}/v2/${REPOSITORY}/manifests/${TAG_OLD}")
curl -X PUT -H "Content-Type: application/vnd.docker.distribution.manifest.v2+json" -d "${MANIFEST}" "${REGISTRY_NAME}/v2/${REPOSITORY}/manifests/${TAG_NEW}"

Upvotes: 5

dvnguyen
dvnguyen

Reputation: 3022

I'm not aware of tagging a docker image directly on docker hub. There's a workaround for your problem, that is tagging the image with two tags when building it. docker build allows to create multiple tags for one build:

docker build -t org/foo:34f8a342 -t org/foo:latest .

Upvotes: 1

Related Questions