Skip to Content

Docker registry - operations on API

Creating some script and want get to docker registry from API? Let's do some CURL

Share on:

Instead of using Docker CLI commands - we can communicate with Docker registry with GET/POST methods of Docker Registry HTTP API.
Post include information for V2 of API.

Example setup

For our examples we use docker private registry in container. Currently we have got alpine image and couple of ubuntu images loaded in it.

[lukas@docker-host ~]$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
f628491a985a        registry:2          "/entrypoint.sh /etc…"   About a minute ago   Up About a minute   0.0.0.0:5000->5000/tcp   registry

If you want to use secure connections - look at curl --help and use parameters associated with CA and certificates like --cacert.

Check connection with repository

[lukas@docker-host ~]$ curl  -X GET http://localhost:5000/v2/ -v
Note: Unnecessary use of -X or --request, GET is already inferred.
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 5000 (#0)
> GET /v2/ HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Length: 2
< Content-Type: application/json; charset=utf-8
< Docker-Distribution-Api-Version: registry/2.0
< X-Content-Type-Options: nosniff
< Date: Wed, 15 Apr 2020 13:34:39 GMT
<
* Connection #0 to host localhost left intact
{}[lukas@docker-host ~]$

List images in registry

[lukas@docker-host ~]$ curl  -X GET http://localhost:5000/v2/_catalog
{"repositories":["alpine","ubuntu"]}

Get available tags for image

Check tags for ubuntu image:

[lukas@docker-host ~]$ curl  -X GET http://localhost:5000/v2/ubuntu/tags/list
{"name":"ubuntu","tags":["latest","19.10","19.04","18.10"]}

Check if manifest exists

[lukas@docker-host ubuntu-19.10]$ curl -I  http://localhost:5000/v2/ubuntu/manifests/19.10
HTTP/1.1 200 OK
Content-Length: 5568
Content-Type: application/vnd.docker.distribution.manifest.v1+prettyjws
Docker-Content-Digest: sha256:84328f1bc9d8105cb4e5f014cac3eeafda161b58128fb87ea7541f0ec1710669
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:84328f1bc9d8105cb4e5f014cac3eeafda161b58128fb87ea7541f0ec1710669"
X-Content-Type-Options: nosniff
Date: Wed, 15 Apr 2020 14:30:43 GMT

Pull image manifest

Get metadata for Ubuntu 19.10 image:

[lukas@docker-host ~]$ curl  -X GET http://localhost:5000/v2/ubuntu/manifests/19.10
{
   "schemaVersion": 1,
   "name": "ubuntu",
   "tag": "19.10",
   "architecture": "amd64",
   "fsLayers": [
      {
         "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
      },
      {
         "blobSum": "sha256:9460de83957c509dd234ede9ea96d4d03b7f9cd252ef1497844f8450dedb6570"
      },
      {
         "blobSum": "sha256:22752cd61bd53e9ac71e22fef539c165b3e11b368c1e54ca947260e317c4870a"
      },
      {
         "blobSum": "sha256:25405ed4f245fc5627d0b03996d04c11d492c7a9ff937f4562a18e8757c39434"
      },
      {
         "blobSum": "sha256:eeacba527962683a1b026af611fe162d35281159762b699172caa48c69480f79"
      }
   ],
   "history": [
      {
         "v1Compatibility": "{\"architecture\":\"amd64\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/bash\"],\"ArgsEscaped\":true,\"Image\":\"sha256:c50c27e497214ed2e11462fe012e6f03516e8c22a96da7c8d43b66ee3d419754\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"container\":\"245856bcc226438a902b39d236a66777383561c260605f12ca83a4b9bb429a21\",\"container_config\":{\"Hostname\":\"245856bcc226\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) \",\"CMD [\\\"/bin/bash\\\"]\"],\"ArgsEscaped\":true,\"Image\":\"sha256:c50c27e497214ed2e11462fe012e6f03516e8c22a96da7c8d43b66ee3d419754\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"created\":\"2020-03-20T19:20:36.847728128Z\",\"docker_version\":\"18.09.7\",\"id\":\"72c4b1dbff9f650f052e3e8d842d1f9a1c8d5a9a56372450cc655bcfbb51eafc\",\"os\":\"linux\",\"parent\":\"1865fab8daaf362fa003da426809977138cf316781c927ee927b560663ad8899\",\"throwaway\":true}"
      },
      {
         "v1Compatibility": "{\"id\":\"1865fab8daaf362fa003da426809977138cf316781c927ee927b560663ad8899\",\"parent\":\"a66a208f5a6d08af66e96314881c2a43adbcc381950cb0dc23b6e6361cac674b\",\"created\":\"2020-03-20T19:20:36.666791568Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c mkdir -p /run/systemd \\u0026\\u0026 echo 'docker' \\u003e /run/systemd/container\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"a66a208f5a6d08af66e96314881c2a43adbcc381950cb0dc23b6e6361cac674b\",\"parent\":\"27fd7159a11d0bb84f765b89ad037900f915d2cdd72bdbc67e8af983b778f7f7\",\"created\":\"2020-03-20T19:20:35.896375229Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c set -xe \\t\\t\\u0026\\u0026 echo '#!/bin/sh' \\u003e /usr/sbin/policy-rc.d \\t\\u0026\\u0026 echo 'exit 101' \\u003e\\u003e /usr/sbin/policy-rc.d \\t\\u0026\\u0026 chmod +x /usr/sbin/policy-rc.d \\t\\t\\u0026\\u0026 dpkg-divert --local --rename --add /sbin/initctl \\t\\u0026\\u0026 cp -a /usr/sbin/policy-rc.d /sbin/initctl \\t\\u0026\\u0026 sed -i 's/^exit.*/exit 0/' /sbin/initctl \\t\\t\\u0026\\u0026 echo 'force-unsafe-io' \\u003e /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \\t\\t\\u0026\\u0026 echo 'DPkg::Post-Invoke { \\\"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\\\"; };' \\u003e /etc/apt/apt.conf.d/docker-clean \\t\\u0026\\u0026 echo 'APT::Update::Post-Invoke { \\\"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\\\"; };' \\u003e\\u003e /etc/apt/apt.conf.d/docker-clean \\t\\u0026\\u0026 echo 'Dir::Cache::pkgcache \\\"\\\"; Dir::Cache::srcpkgcache \\\"\\\";' \\u003e\\u003e /etc/apt/apt.conf.d/docker-clean \\t\\t\\u0026\\u0026 echo 'Acquire::Languages \\\"none\\\";' \\u003e /etc/apt/apt.conf.d/docker-no-languages \\t\\t\\u0026\\u0026 echo 'Acquire::GzipIndexes \\\"true\\\"; Acquire::CompressionTypes::Order:: \\\"gz\\\";' \\u003e /etc/apt/apt.conf.d/docker-gzip-indexes \\t\\t\\u0026\\u0026 echo 'Apt::AutoRemove::SuggestsImportant \\\"false\\\";' \\u003e /etc/apt/apt.conf.d/docker-autoremove-suggests\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"27fd7159a11d0bb84f765b89ad037900f915d2cdd72bdbc67e8af983b778f7f7\",\"parent\":\"b14defeb827d49a068f1d1bb280e312add99650430b71e881f1f6f304d81aefe\",\"created\":\"2020-03-20T19:20:35.087356956Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c [ -z \\\"$(apt-get indextargets)\\\" ]\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"b14defeb827d49a068f1d1bb280e312add99650430b71e881f1f6f304d81aefe\",\"created\":\"2020-03-20T19:20:34.200290542Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) ADD file:537f9883fb90d19383082b8ac20c17b581db9045a48fa28b83cab73fe317047d in / \"]}}"
      }
   ],
   "signatures": [
      {
         "header": {
            "jwk": {
               "crv": "P-256",
               "kid": "EAGI:M5GN:CQT7:AKOB:DROQ:BYVZ:BU3O:3OCP:UPRN:L6QL:FZVJ:DVNX",
               "kty": "EC",
               "x": "cXGUHd8wxSJc11dZDTWLOJ_rvGX5HLjLwh-rtDyj1KU",
               "y": "7gfzvzTXiH2NHhGvdojb2XFLkRvod4gakPyR_6hgJDE"
            },
            "alg": "ES256"
         },
         "signature": "DdFJAdzi0t9LrViJrko_ZHwbX_nQwZlLtnkNe1piWVlYrh-8vxtuoNi5NcKvIfwUDK_rosCg705Ob2Gyk26rTQ",
         "protected": "eyJmb3JtYXRMZW5ndGgiOjQ5MjEsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAyMC0wNC0xNVQxMzo1OTowMFoifQ"
      }
   ]
}

Download image layer via API

From manifest file we get list of layers - fsLayers section - with sha256 hashes we can download each layers of image:

[lukas@docker-host ubuntu-19.10]$ curl  -X GET http://localhost:5000/v2/ubuntu/blobs/sha256:eeacba527962683a1b026af611fe162d35281159762b699172caa48c69480f79 --output sha256:eeacba527962683a1b026af611fe162d35281159762b699172caa48c69480f79
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 26.9M  100 26.9M    0     0   350M      0 --:--:-- --:--:-- --:--:--  350M

After downloading all layers:

[lukas@docker-host ubuntu-19.10]$ ll
total 27660
-rw-rw-r--. 1 lukas lukas      844 Apr 15 16:07 sha256:22752cd61bd53e9ac71e22fef539c165b3e11b368c1e54ca947260e317c4870a
-rw-rw-r--. 1 lukas lukas    30632 Apr 15 16:07 sha256:25405ed4f245fc5627d0b03996d04c11d492c7a9ff937f4562a18e8757c39434
-rw-rw-r--. 1 lukas lukas      163 Apr 15 16:07 sha256:9460de83957c509dd234ede9ea96d4d03b7f9cd252ef1497844f8450dedb6570
-rw-rw-r--. 1 lukas lukas       32 Apr 15 16:07 sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
-rw-rw-r--. 1 lukas lukas 28276050 Apr 15 16:08 sha256:eeacba527962683a1b026af611fe162d35281159762b699172caa48c69480f79

Delete image via API

By default deleting images is not allowed.
If you want allow deleting start registry container with variable -e REGISTRY_STORAGE_DELETE_ENABLED=true

Delete command only accepts digest hash as reference to image - tags are not supported - we get this digest when we uploading image into repository:

[lukas@docker-host ~]$ curl  -X DELETE  http://localhost:5000/v2/ubuntu/manifests/sha256:7ce552ad1c3e94a5c3d2bb24c07000c34a4bb43fd9b379652b2c80593a018e80

We can check that there is no longer Ubuntu 19.10 image in our repository:

[lukas@docker-host ~]$ curl  -X GET http://localhost:5000/v2/ubuntu/tags/list
{"name":"ubuntu","tags":["latest","19.04","18.10"]}