Tagging images using Docker Registry HTTP API v2

Problem

Docker Registry HTTP API v2 is incompatible with v1 and there’s no dedicated method to tag an existing image. Instead you should deal with image manifests.

Solution

There are 2 manifest schemas in v2 API:

  • version 1 which requires to use signed manifests
  • version 2 (available in Docker Registry >= 2.3) which allows you to use non-signed ones

Working with version 2 is much simpler and that’s why we’re going to use it.

The idea is very simple:

  • download a manifest of an image
  • upload the same manifest under a new tag

Step-by-step guide

  • Prerequisites:
$ docker --version
Docker version 1.10.3, build 9419b24-unsupported
$ registry --version
registry github.com/docker/distribution v2.4.0+unknown
  • Start registry 2.4:
$ sudo registry serve /etc/docker-distribution/registry/config.yml
  • Install an image in the registry:
$ sudo docker pull busybox
$ sudo docker tag busybox localhost:5000/mybusybox
$ sudo docker push localhost:5000/mybusybox
  • Get manifest of the uploaded image:
$ curl 'http://localhost:5000/v2/mybusybox/manifests/latest' \
-H 'accept: application/vnd.docker.distribution.manifest.v2+json' \
> manifest.json

Result from manifest.json (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 'http://localhost:5000/v2/mybusybox/manifests/new_tag' \
-H 'content-type: application/vnd.docker.distribution.manifest.v2+json' \
-d '@manifest.json'
  • Check that the new tag has been created:
$ curl 'http://localhost:5000/v2/mybusybox/tags/list'
{"name":"mybusybox","tags":["latest","new_tag"]}

Known issues

Docker pre-1.10 generates manifests only using schema 1. So if you push an image, it’s going to have only that manifest. And if you try to retrieve the manifest of schema 2 via curl, accept header will be effectively ignored and you’ll always get back manifest of schema 1. That’s because the registry (at least 2.4) does not support conversion from schema 1 to 2.

comments powered by Disqus