Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save andreimerlescu/3958c42c95b813396bc3c65fe51d1b84 to your computer and use it in GitHub Desktop.
Save andreimerlescu/3958c42c95b813396bc3c65fe51d1b84 to your computer and use it in GitHub Desktop.

To run a Docker Registry via Docker-Compose with HTPASSWD Auth

1. Recommended Minimum Purchases

The total cost of your setup is going to be $204.27/year ($17.03/month or 2 cups of Coffee at Starbucks) What you'll get is a private docker registry (v2) with 100GB of dedicated storage for your containers.

  1. Create a $5 VM by signing up for DigitalOcean and deploying a Marketplace Docker container. Make sure you add Block Storage! $100GB for $10/month is not expensive and you will thank me later. I also recommend you enable backups for $1.00/mmonth.
  2. Register an awesome domain name at Epik (.xyz domains are $0.89 for the first year [2019] and then just $8.50/year thereafter)
  3. Purchase a $3.77/year SSL certificate from ssls.com

2. Initial Setup

  1. SSH into the VM

  2. Update the system and install some packages to get us started:

apt-get update && apt-get upgrade -y && apt-get install fail2ban apache2-utils -y

fail2ban will add additional security to SSH authentication attempts apache2-utils will allow us to configure htpasswd credentials for securing your registry

  1. From DigitalOcean, create a Firewall policy for your Docker Registry by opening port 5000 and adding your new container (make sure you have SSH added if you wish)

  2. Add a second firewall configuration by using ufw

ufw default deny incoming
ufw default allow outgoing
ufw limit ssh
ufw allow 5000
  1. In Epik, after you've registered your domain name, add a DNS A record like so:
Name         Type     IP                       TTL
registry     A        YOUR.DIGITAL.OCEAN.IP    300
  1. If you do not wish to wait for the DNS records to propagate throughout the internet and your service provider, you can use your /etc/hosts file:
sudo vi /etc/hosts

Add the following line, replacing of course the relevant information with your information.

YOUR.DIGITAL.OCEAN.IP registry.YOURDOMAIN.COM

Just make sure you don't leave that after a few days since it may cause issues in the future if you forget about it.

  1. Once your server is configured with Docker and is secured using the UFW + DigitalOcean Firewall, then we can proceed...

3. Getting your SSL Certificate

  1. Once you've purchased your SSL certificate from SSLs.com you can begin the activation process by generating your CSR (Certificate Signing Request):
# from your server - do not generate on your host machine

mkdir -p /etc/ssl/registry
cd /etc/ssl/registry
openssl req -new -newkey rsa:2048 -nodes -keyout yourdomain_com.pem -out yourdomain_com.csr -subj /CN=yourdomain.com; cat yourdomain_com.csr

Replace yourdomain_com with whatever your domain is, for example.com use example_com, for help.xyz use help_xyz, etc.

  1. Copy the contents of the CSR generated file and paste it into SSLs.com

  2. Perform the domain verification using DNS by following the instructions here for more information about this process. The section is titled DNS-based validation and its at the bottom of the page.

  3. Once the domain ownership is verified, you will receive an email with your SSL certificate and the associated CA chain certificates. We must combine the certs together into one file.

# on your host machine

unzip yourdomain_com.zip
cd yourdomain_com
cat yourcomain_com.crt yourdomain_com.ca-bundle > yourdomain_com.crt.bundle
  1. Back on your server, create the following file
vi /etc/ssl/registry/yourdomain_com.crt

Keep the vi window open until you complete step 3.6

  1. Copy the contents of yourdomain_com.crt.bundle to your clipboard. If you're on macOS you can use
cat yourdomain_com.crt.bundle | pbcopy
  1. Then paste the contents of that certificate back onto your server in the vi window from step 3.5 into /etc/ssl/registry/yourdomain_com.crt.

  2. Save the file.

  3. Verify you have both required files:

root@docker-registry-01:~# ls -la /etc/ssl/registry
total 20
drwxr-xr-x 2 root root 4096 Sep  4 13:38 .
drwxr-xr-x 5 root root 4096 Sep  4 13:38 ..
-rw-r--r-- 1 root root 4507 Sep  4 13:38 yourdomain_com.crt
-rw-r--r-- 1 root root  288 Sep  4 13:38 yourdomain_com.key
-rw-r--r-- 1 root root  288 Sep  4 13:38 yourdomain_com.csr

4. Installing Required Components Onto Your Registry Server

  1. Create your auth directory to store the htpasswd inside:
mkdir /root/auth
  1. Create a username/password for authenticating into your private docker registry:
htpasswd -B -c /root/auth/htpasswd username
  1. Find the name of your mounted block storage volume
root@docker-registry-01:~# ls -la /mnt
total 12
drwxr-xr-x  3 root root 4096 Sep  4 13:33 .
drwxr-xr-x 23 root root 4096 Sep  4 13:33 ..
drwxr-xr-x  4 root root 4096 Jun  1 02:47 volume_nyc3_01

You'll need to use the volume_nyc3_01 string (whatever it is that shows up on your container) in step 5.1.

5. Setup Docker-Compose

  1. Create a new file in /root called docker-compose.yaml using:
vi /root/docker-compose.yaml
  1. Add the following contents:
version: '3.4'
services:
  registry:
    restart: always
    image: registry:2
    ports:
      - 5000:5000
    environment:
      REGISTRY_HTTP_ADDR: 0.0.0.0:5000
      REGISTRY_HTTP_TLS_CERTIFICATE: /certs/_YOUR_SSL_CRT_FILENAME_.crt
      REGISTRY_HTTP_TLS_KEY: /certs/_YOUR_SSL_KEY_FILENAME_.key
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
    volumes:
      - /mnt/_MOUNTED_VOLUME_NAME_/docker-registry:/var/lib/registry
      - /etc/ssl/registry:/certs
      - /root/auth:/auth
  1. Replace the following components of the file:
Placeholder Replace With
_MOUNTED_VOLUME_NAME_ Name of the folder from step 4.3
_YOUR_SSL_CRT_FILENAME_ Name of the respective files from step 3.9
_YOUR_SSL_KEY_FILENAME_ Name of the respective files from step 3.9

6. Starting Docker

  1. Boot your container
cd /root
docker-compose up -d
  1. Verify your container is running:
root@docker-registry-01:~# docker-compose ps
     Name                    Command               State           Ports
---------------------------------------------------------------------------------
root_registry_1   /entrypoint.sh /etc/docker ...   Up      0.0.0.0:5000->5000/tcp

7. Test your setup

  1. From your host machine, run the following:
docker login registry.yourdomain.com:5000
Username: username
Password: 
Login Succeeded

8. Pushing Containers To Your Registry

  1. Simply name your containers like so:
docker pull nginx:latest
docker tag nginx:latest registry.yourdomain.com:5000/nginx:latest
docker push registry.yourdomain.com:5000/nginx:latest
  1. If you're using docker build, just make sure your image name is prepended with registry.yourdomain.com:5000/ before pushing, otherwise it may end up not on your private registry!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment