how to tag image in docker registry v2 [duplicate]
Asked Answered
S

5

26

We have logic in our CI-CD that tags (via REST) staging image to latest (if tests are successful). This worked on registry v1.

We now moved to v2 api, and I can't find documentation on how to "add" tags to existing image in registry. I'm in a step that can bring the "manifest" of some staging image, but not sure how to add tag and POST it via http.

I tried to send the following inputs:

  1. "tag": "staging","latest",
  2. "tag": ["staging","latest"], and more
{
    "schemaVersion": 1,
    "name": "configservice",
    "tag": "staging",
    "architecture": "amd64",
    "fsLayers": [...
Skardol answered 10/5, 2016 at 9:50 Comment(1)
There are multiple tools that do this today, including skopeo, crane, and regclient.Subsidence
F
33

If you have Docker Registry that supports manifest schema version 2, you can just upload the manifest of an existing image under a new tag.

For example let's assume that you want to tag latest version of busybox image. The steps would be:

Download the existing manifest:

curl '<registry_url>/v2/mybusybox/manifests/latest' \
-H 'accept: application/vnd.docker.distribution.manifest.v2+json' \
> manifest.json

Here's what the manifest might look like (notice that schemaVersion is 2):

{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   "config": {
      "mediaType": "application/octet-stream",
      "size": 1459,
      "digest": "sha256:2b8fd9751c4c0f5dd266fcae00707e67a2545ef34f9a29354585f93dac906749"
   },
   "layers": [
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": 667590,
         "digest": "sha256:8ddc19f16526912237dd8af81971d5e4dd0587907234be2b83e249518d5b673f"
      }
   ]
}

Upload the manifest under a new tag:

curl -XPUT '<registry_url>/v2/mybusybox/manifests/new_tag' \
-H 'content-type: application/vnd.docker.distribution.manifest.v2+json' \
-d '@manifest.json'

Detailed step-by-step guide is give in this post.

Fukien answered 13/7, 2016 at 22:4 Comment(4)
You should post the instructions here in case the website goes down -- meta.stackexchange.com/questions/8231/…Monda
Doesn't work for me using a nexus3 docker registry. <Response [404]> {"errors":[{"code":"MANIFEST_UNKNOWN","message":"manifest unknown","detail":[{"Name":"testrepo"},{"Tag":"newtag"}]}]}Varityper
Regarding my last comment, I think this is a bug in nexus, so I made a ticket: issues.sonatype.org/browse/NEXUS-27253Varityper
What is the repository URL for docker hub?Welcome
A
23

This isn't a direct answer to your question, but I have always done the following...

docker pull myimage:staging
docker run myimage:staging test  # this is optional
docker tag myimage:staging myimage:release
docker push myimage:release

Note that docker pull will download the image, but if layers already exists on the registry, docker push will not upload everything again.

Abdullah answered 12/7, 2016 at 22:5 Comment(3)
This is definitely a working solution, but it requires to have docker binary, possibly running it as root. Also it might take considerable amount of time, because it involves image downloading.Fukien
Based on the question, we are running tests on the image to validate it- so it must already exist (either having been built or downloaded) on the CI machine. This doesn't introduce any additional concerns that the "test" step doesn't (just the lag from the second docker push which is quite fast in the event of a retag.Abdullah
This does not work if you have multi-platform images and the original image you are trying to re-tag is not on the local machine (i.e. you first have to pull it). This is because "docker pull" only pulls the image layers that match the local machine's platform architecture, then if you push the new tag(s) you will only push an image with a single platform architecture layer.Amphibole
T
10

I just wanted to add, since this came up in my search results, that Google Container Registry includes the add-tag command to do this directly.

gcloud container images add-tag gcr.io/project/image:old-tag gcr.io/project/image:new-tag

The workflow described by wheleph above worked, but resulted in the creation of a new container rather than applying an additional tag to the existing one.

Thessalonian answered 13/12, 2018 at 20:48 Comment(4)
And here is how to do the equivalent in AWS: davin.ninja/amazon-ecr-adding-tag-image-already-pushedTanguay
Just as a clarification- the docker tag && docker push workflow above does NOT actually create any new containers (or images). When the daemon or registry sees that a tag refers to the same underlying image, the API just adds a reference from the new tag to the old image. The registry api is the same, the new manifest refers to the same underlying images/layers. The api provided by ecr and gcloud is of course nicer though :)Abdullah
If memory serves, I tested Google Cloud's behaviour at the time and found that it interpreted the command as creating a new image, although of course that was several years ago. As for retagging from the API, both Google Cloud and AQS have the advantage that their APIs don't require you to have a local copy of the image, which might be friendlier to some workflows.Thessalonian
The described method for AWS doesn't appear to work anymore, but instead creates a new image in the ECR repository rather than adding a tag to an existing image.Desideratum
A
6

You can achieve this with docker buildx imagetools create

docker buildx imagetools create myregistry.com/myimage:latest --tag myregistry.com/myimage:staging

this will simply download the image manifest of myregistry.com/myimage:latest and re-tag (and push) it as myregistry.com/myimage:staging

NOTE: this will also retain the multi-platform manifest list when you "re-tag" (e.g. when your image is build for both linux/arm64 and linux/amd64). Where as the conventional docker pull/push strategy will only retain the image manifest for the platform/architecture of the system you do the pull/push from.

P.S. this is repost of my answer here

Amphibole answered 30/12, 2021 at 1:35 Comment(1)
This is the most efficient answer that worked for me. Thank you for the great tip!Manvel
O
5

This answer works only for changing image tag, but I wanted to change the repository name too.

Thanks to Nicholas Dille's 'How to tag docker images without pulling them' post, I was able to change the repoName too! With help from his nicholasdille/PowerShell-RegistryDocker project project:

  1. get manifests (in v2 schema)
  2. post every layer.digest in the new repo
  3. post config.layer
  4. put whole manifest to new repo

details:

  1. GET manifest from reg:5000/v2/{oldRepo}/manifests/{oldtag} withaccept header:application/vnd.docker.distribution.manifest.v2+json

  2. For every layer : POST reg:5000/v2/{newRepo}/blobs/uploads/?mount={layer.digest}&from={oldRepoNameWithaoutTag}

  3. POST reg:5000/v2/{newRepo}/blobs/uploads/?mount={config.digest}&from={oldRepoNameWithaoutTag}

  4. PUT reg:5000/v2/{newRepo}/manifests/{newTag} with content-type header:application/vnd.docker.distribution.manifest.v2+json and body from step 1 response

  5. enjoy!

Ossified answered 19/1, 2020 at 14:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.