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.