Docker Registry API

How to list images and tags in the docker registory? How to delete image(layers) in docker registory? These are general demands in my daily work, let’s figure them out.

A brife digression: The OpenShift platform has web UI to deal with images in integrated docker registry (it is called imagestream in OpenShift), usually after you login to terminal, run oc version will show you the web address. You can list and delete imagestream there.

For example, I use OpenShift integrated docker registry and push my docker images to a project called datastage (I configuring the setting so other project can pull images from this project):

Resurces

Docker Registry HTTP API V2 Registry 清理镜像 v2 Docker registry authentication Registry tool Git project Cleanup Your Docker Registry

Quick Set up

After installing docker, get and run docker registry from Docker Offical Images - registry.

1
docker pull registry

you will get:

1
2
3
4
docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
registry latest f32a97de94e1 3 months ago 25.8MB

then run it locally with image deletion enabled:

1
docker run -d -p 5000:5000 -e REGISTRY_STORAGE_DELETE_ENABLED=true --restart always --name registry registry

To remove images, you need to setup docker registry with delete enabled(by default it’s off), see my blog Docker Registry Configure

1
2
3
4
docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3021266dca1f registry "/entrypoint.sh /etc..." 2 seconds ago Up 1 second 0.0.0.0:5000->5000/tcp registry

Next, let’s use busybox to illustrate:

1
2
3
docker pull busybox
docker tag busybox localhost:5000/busybox:v1
docker push localhost:5000/busybox:v1

Insecure Docker Registry

Quick set up will give you a insecure private docker registry (means no docker login and use http to access API).

Note that you can use -v option in curl command to get verbose message such as HEADER information.

Check Availability

1
2
3
4
5
6
7
8
curl -k --head -X GET http://localhost:5000/v2/

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: Sun, 23 Jun 2019 05:20:01 GMT

This means registry is accessable and user has permission.

List Images

1
2
3
curl -k -X GET http://localhost:5000/v2/_catalog

{"repositories":["busybox"]}

List Image Tags

1
2
3
curl -k -X GET http://localhost:5000/v2/busybox/tags/list

{"name":"busybox","tags":["v1"]}

Delete Images

Deletion of unused digests of docker images to avoid unnecessary space growth in a private docker registry

Deletion is more complicated than list, from Deleting an Image API, there are 2 main steps:

Delete through API

  1. Get the digest of the image with tag v1
1
2
3
4
5
6
7
8
9
10
curl -k --head -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://localhost:5000/v2/busybox/manifests/v1

HTTP/1.1 200 OK
Content-Length: 527
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:bf510723d2cd2d4e3f5ce7e93bf1e52c8fd76831995ac3bd3f90ecc866643aff
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:bf510723d2cd2d4e3f5ce7e93bf1e52c8fd76831995ac3bd3f90ecc866643aff"
X-Content-Type-Options: nosniff
Date: Sun, 16 Jun 2019 20:12:07 GMT

Note when deleting a manifest from a registry version 2.3 or later, the following header must be used when HEAD or GET-ing the manifest to obtain the correct digest to delete: Accept: application/vnd.docker.distribution.manifest.v2+json.

You can refer this Image Manifest V 2, Schema 2 to get more header details.

Here, we use the digest from Docker-Content-Digest field in the header, the vaule is sha256:bf510723d2cd2d4e3f5ce7e93bf1e52c8fd76831995ac3bd3f90ecc866643aff.

Actually, if the docker image is loaded, you can inspect it by:

1
docker inspect localhost:5000/busybox:v1 | less

There is a RepoDigests field that also contains the same digest:

1
2
3
4
5
6
...
"RepoDigests": [
"busybox@sha256:7a4d4ed96e15d6a3fe8bfedb88e95b153b93e230a96906910d57fc4a13210160",
"localhost:5000/busybox@sha256:bf510723d2cd2d4e3f5ce7e93bf1e52c8fd76831995ac3bd3f90ecc866643aff"
],
...
  1. Issue delete command
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
curl -k -v -X DELETE http://localhost:5000/v2/busybox/manifests/sha256:bf510723d2cd2d4e3f5ce7e93bf1e52c8fd76831995ac3bd3f90ecc866643aff

* About to connect() to localhost port 5000 (#0)
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5000 (#0)
> DELETE /v2/busybox/manifests/sha256:bf510723d2cd2d4e3f5ce7e93bf1e52c8fd76831995ac3bd3f90ecc866643aff HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:5000
> Accept: */*
>
< HTTP/1.1 202 Accepted
< Docker-Distribution-Api-Version: registry/2.0
< X-Content-Type-Options: nosniff
< Date: Sun, 16 Jun 2019 20:27:05 GMT
< Content-Length: 0

The response HTTP/1.1 202 Accepted means the deletion succeeds, let’s check the tag again:

1
2
3
curl -k -X GET http://localhost:5000/v2/busybox/tags/list

{"name":"busybox","tags":null}

Note that if the docker registry deletion is not enabled, you will get response {"errors":[{"code":"UNSUPPORTED","message":"The operation is unsupported."}]}.

Delete in File System

Note this way doesn’t required docker registry is deletion enabled!

Actually, docker registry stores image in /var/lib/registry/docker/registry/v2/, there are blobs and repositories directories. blobs directory is where images reside and repositories is where metadata and reference locate.

You need to delete two dirs if you mount docker registry storage in host:

1
2
3
rm -rf <mount path>/registry/v2/repositories/busybox/_manifests/tags/v1/index/sha256/<hash dir>

rm -rf <mount path>/registry/v2/repositories/busybox/_manifests/revisions/sha256/<hash dir>

At the time of deleting those dirs; the docker registry should be in read only mode. Nobody should push to registry.

Garbage Collection

However, the API and file system deletions above only remove the metadata or dereference the connection between manifest with layers data in disk, we need to run garbage collection in docker registry to remove layers:

1
docker exec -it registry sh

check space used before clean:

1
2
3
4
du -sch /var/lib/registry/docker/

764.0K /var/lib/registry/docker/
764.0K total

then run garbage collection:

1
bin/registry garbage-collect /etc/docker/registry/config.yml

Note that /etc/docker/registry/config.yml is the configuration file for docker registry.

then if you check space used again

1
2
3
4
du -sch /var/lib/registry/docker/

8.0K /var/lib/registry/docker/
8.0K total

Other Notice

If you have one image with multiple tags and the digests are the same, delete one of them will remove them all.

If you have one image with multiple tags and the digests are different for each tag, deletion is tag-separate.

Secure Docker Registry

In ICP4D cluster, we use secure docker registry with https and login credentials. But first let’s understand how to set up secure docker registry, see my blog <<Secure Docker Registry>>.

login, see .docker/config curl works?

Check Availability

If you don’t have authentication, you will get 401 Unauthorized status, for example, here https://mycluster.icp:8500 is the private secure docker registry location:

1
2
3
4
5
6
7
8
curl --head -k -X GET https://mycluster.icp:8500/v2/

HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
Www-Authenticate: Bearer realm="https://mycluster.icp:8600/image-manager/api/v1/auth/token",service="token-service"
Date: Mon, 24 Jun 2019 16:14:10 GMT
Content-Length: 87

Here Www-Authenticate tells you Auth Server address.

In my OpenShift cluster:

1
2
3
4
5
6
7
8
9
10
11
curl -k --head -X GET https://172.30.159.11:5000/v2/

HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
Www-Authenticate: Bearer realm="https://172.30.159.11:5000/openshift/token"
X-Registry-Supports-Signatures: 1
Date: Mon, 24 Jun 2019 16:37:40 GMT
Content-Length: 87

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}

Need to apply token from Auth Server.

1
2
3
4
5
6
7
8
9
======================================================================================
I think I get stuck here...
the situation is:
1. I have docker login ability
2. where can I get the token to do API access? auth server, where, how?
3. the platform use what to secure docker registry?

icp4d cluster is more transparent the Openshfit
======================================================================================
1
curl -u openshift:NOyEoOrA0FDm2IgYqlHCDkDepQ7I0vw-7Sx8RzPUmzw -X GET "https://172.30.159.11:5000/openshift/token?service=172.30.159.11:5000&scope=repository:demo1-ds/busybox:pull,push"

https://docs.docker.com/registry/spec/auth/token/

List Images

1
2


List Tags

1
2


Remove Images

1
2


0%