Docker Registry

Registry is a simple container image registry container.


Usage

docker run --detach --name registry --restart always \
  --mount type=bind,src=/host/path/to/data/dir,dst=/var/lib/registry \
  --env REGISTRY_STORAGE_DELETE_ENABLED=true \
  --env REGISTRY_HTTP_HOST=http://registry.example.com \
  --publish 0.0.0.0:80:5000 \
  docker.io/library/registry:2

Test the registry by accessing (either in a browser or through curl(1)) http://registry.example.com/v2.

Pull the list of available container images with:

curl -X GET http://registry.example.com/v2/_catalog

Pull the list of available tags for an image with:

curl -X GET http://registry.example.com/v2/$IMAGE/tags/list

Encryption

Docker Registry is a built-in encryption facility, but putting the registry behind a reverse proxy is significantly more straightforward and flexible.

With haproxy(8):

global
  ssl-default-bind-options ssl-min-ver TLSv1.2
  maxconn 1024

defaults
  mode http
  default-server init-addr none

resolvers docker_dns
  nameserver docker 127.0.0.11:53

backend registry_backend
  server registry1 registry:5000 check resolvers docker_dns

frontend http_frontend
  bind :::8080 v4v6
  bind :::8443 v4v6 ssl crt /var/letsencrypt/registry.example.com.pem alpn h2,http1.1

  http-request redirect scheme https unless { ssl_fc }

  acl registry hdr(host) -i registry.example.com
  use_backend registry_backend if registry

Then try deploying like:

docker run --detach --name registry --restart always \
  --mount type=bind,src=/host/path/to/data/dir,dst=/var/lib/registry \
  --env REGISTRY_STORAGE_DELETE_ENABLED=true \
  --env REGISTRY_HTTP_HOST=https://registry.example.com \
  --env REGISTRY_HTTP_SECRET=somesecretpassphrase \
  docker.io/library/registry:2

docker run --detach --name haproxy --restart always \
  --mount type=bind,src=/host/path/to/letsencrypt/dir,dst=/var/letsencrypt,readonly \
  --mount type=bind,src=/host/path/to/haproxy/conf/dir,dst=/usr/local/etc/haproxy,readonly \
  --publish 80:8080 --publish 443:8443 \
  haproxy:latest

docker network create my-bridge
docker network connect my-bridge registry
docker network connect my-bridge haproxy

Authentication

Docker Registry supports authentication, but only over encrypted connections. See the above section first.

To setup authentication, first generate an htpasswd file.

docker run --entrypoint htpasswd httpd:2 -Bbn $USER $PASSWD > /host/path/to/auth/dir/htpasswd

Then destroy and re-deploy the registry, now with some additional options and an additional bind mount.

docker run --detach --name registry --restart always \
  --mount type=bind,src=/host/path/to/data/dir,dst=/var/lib/registry \
  --mount type=bind,src=/host/path/to/auth/dir,dst=/auth,readonly \
  --env REGISTRY_AUTH=htpasswd \
  --env "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  --env REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  --env REGISTRY_STORAGE_DELETE_ENABLED=true \
  --env REGISTRY_HTTP_HOST=https://registry.example.com \
  docker.io/library/registry:2

To perform the same test as above, try:

curl -X GET -u $USER:$PASSWD https://registry.example.com/v2/_catalog
curl -X GET -u $USER:$PASSWD https://registry.example.com/v2/$IMAGE/tags/list

High Availability

Update the haproxy(8) configuration above like:

backend registry_backend
  server registry1 registry1:5000 check resolvers docker_dns
  server registry2 registry2:5000 check resolvers docker_dns

Then run as many containers as needed.

docker run --detach --name registry1 --restart always \
  --mount type=bind,src=/host/path/to/data/dir,dst=/var/lib/registry \
  --env REGISTRY_STORAGE_DELETE_ENABLED=true \
  --env REGISTRY_HTTP_HOST=https://registry.example.com \
  --env REGISTRY_HTTP_SECRET=somesecretpassphrase \
  docker.io/library/registry:2
docker network connect my-bridge registry1

docker run --detach --name registry2 --restart always \
  --mount type=bind,src=/host/path/to/data/dir,dst=/var/lib/registry \
  --env REGISTRY_STORAGE_DELETE_ENABLED=true \
  --env REGISTRY_HTTP_HOST=https://registry.example.com \
  --env REGISTRY_HTTP_SECRET=somesecretpassphrase \
  docker.io/library/registry:2
docker network connect my-bridge registry2

The REGISTRY_HTTP_SECRET environment variable has to be set explicitly to share the encrypted registry between processes.


CategoryRicottone

Docker/Registry (last edited 2023-05-25 00:55:13 by DominicRicottone)