When we refer to containers, we now usually refer to the combination
of cgroups, namespaces, and a packed system image. To store and
distribute these packed system images, container runtime tooling such
as Docker relies on registries to retrieve named images.

While numerous project are already available in public registries,
a few cases mandate relying on a private container image store:

A registry close to workloads will avoid tying a service’s availability to that of a third-party services.

Using containers as build artifacts for proprietary code require a private registry.

A central docker registry can serve as the coordination tool for the developers,
continuous integration, and configuration management.

There are multiple ways to deploy the registry. Since the storage is
decoupled from the registry service, several registries may be deploy
pointing to a single bucket.
This can be useful to provide fast local registries for build servers
for instance.

Read on for a detailed walk-through of a Docker
compose based installation on Exoscale.

Install prerequisites

To get started, we will start with an Exoscale account and an object storage bucket.

You bucket now contains a folder docker containing the registry files. By
default, a bucket is private. Using Jones Magloire’s Docker Registry
UI, you even get something nice to show.

Exposing a Docker Registry to the Internet

The issue with this solution is that no security is in place. To remain
safe, you have to run a Docker registry everywhere you need it, rely on
the Object Storage authentication system, and be super cautious about sharing
the API key and secret.

To share the Docker Registry across a team and expose it on the Internet, a good
security layer is required. By default, it is fully open to anyone and we should
use it that way on localhost and nothing else.

Our proposed solution is to setup TLS (SSL) in order to encrypt the
communication channel and client certificates to authenticate the users.

Setting up TLS

For the sake of brevity, we will use self-signed certificates. Paul
Czarkowski’s OMGWTFSSL (pardon my french) is a handy container to
create some. Since localhost causes problem, work on your local IP address. Feel
free to use a public IP address or even a domain name.

Let’s fix that by telling Docker that our self-signed
certificate is OK. We have to install the Certificate Authority (CA) root
certificate in the Docker client. If you’re using a domain name, replace
192.168.0.42 by it.

At this point, the traffic between the registry and the docker client is
encrypted but anyone can still read from it. We need an authentication
mechanism.

Authentication using Client Certificates

The Docker registry supports client certificates, which is awesome! The
Registry can restrict TLS connections to certificates that were
signed by a given list of Certificate Authorities. This is a stronger
kind of authentication than using a username and password combination.

The Registry need this little change in its configuration to activate
the client certificates authorities.

Conclusion

A private Docker Registry becomes a vital part of a Containers based
infrastructure. Having it in the same data center as your machines will
drastically speed up pulling images. When doing so, make sure all your
containers are safely protected and that communication channels are
strongly encrypted.