How to setup private docker registry for your projects to save money
Vitaliy Yanchuk
Posted on July 17, 2019
I got to use docker for my projects which are not open-sourced, some of them are hobby projects or try-outs which I don't want yet to publish, so I need to store them privately.
DockerHub only allows 1 private image to be stored in the Free plan, 5 images for 7$ and 10 for 12$ which is decent price for production projects, but for personal hobby projects may be a lot.
I have a 5$ server on DigitalOcean for personal needs, which I want also to use as a docker registry, and CI for my private projects.
The steps in this guide are not the only one possible, there are many ways to achieve same result, but I tried to make it as quick and as simple as possible, I will describe each configuration why it is required.
Prerequisites
I am using Ubuntu 18.04, so all commands will be related to this system.
You need to have Docker and Docker Compose installed on your host Official docs:
https://docs.docker.com/install/linux/docker-ce/ubuntu/You need to have an installed nginx.
Examples assume you have a domain:
example.com
, and that you want to start registry on:registry.example.com
Step 1: Setup nginx
I don't use nginx as docker container as I have also some other static sites on same machine, which I don't want to wrap into containers. And also I find it easier to have nginx outside containers and on the host machine.
ssh to host machine and install nginx, if you don't have it yet
apt install nginx
Then create nginx configuration for your domain:
/etc/nginx/sites-enabled/registry.example.com
upstream docker-registry {
server 127.0.0.1:5000;
}
server {
server_name registry.example.com;
server_name_in_redirect off;
# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# required to avoid HTTP 411: see Issue #1486 (https://github.com/moby/moby/issues/1486)
chunked_transfer_encoding on;
location /v2/ {
# Do not allow connections from docker 1.5 and earlier
# docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
return 404;
}
proxy_pass http://docker-registry;
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}
Because we would use BasicAuth to authenticate to registry we need to setup SSL so that our login/password is not taken by man in the middle attack.
Currently this nginx config does not support SSL which is required to make our registry accessible from outside.
We would use CertBot to update our nginx configuration to support SSL.
Step 2: CertBot
Install CertBot as described here: https://certbot.eff.org/lets-encrypt/ubuntubionic-nginx
Now you can run command:
certbot --nginx -d registry.example.com
It would modify /etc/nginx/sites-enabled/registry.example.com
so it supports SSL.
Step 3: Docker Registry
Official doc is here: https://docs.docker.com/registry/deploying/
The official doc is quite long, and describes lots of options for different use cases
Just connect via ssh to your host, go to /root folder.
mkdir docker-volumes
mkdir docker-volumes/registry/
mkdir docker-volumes/registry/registry
mkdir docker-volumes/registry/auth
Create there such docker-compose.yml
file:
version: "3"
services:
registry:
restart: always
image: 'registry:2'
ports:
- "5000:5000"
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
volumes:
- /root/docker-volumes/registry/registry:/var/lib/registry
- /root/docker-volumes/registry/auth:/auth
Step 4: Authentication
Then we need to restrict access to registry by login/password, we would use BasicAuth. To do so we need to generate htpasswd file which we would put into registry container. Change testuser/testpassword to your own.
docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > ./docker-volumes/registry/auth/htpasswd
Step 5: Starting it all up
Now we can start registry, run:
docker-compose up -d
Also restart nginx so it loads new config for registry.example.com
/etc/init.d/nginx restart
Step 6: Verify
In order to check that we configured everything correctly, go to console on your local machine, which you would use to build images (your laptop probably), and try to login:
docker login registry.example.com
Use credentials from Step 4
Now it should be all up. In upcoming posts I will write how to setup your private CI using Drone.io so it can use your private registry in its builds.
Posted on July 17, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.