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.
- 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.
- Register an awesome domain name at Epik (.xyz domains are $0.89 for the first year [2019] and then just $8.50/year thereafter)
- Purchase a $3.77/year SSL certificate from ssls.com
-
SSH into the VM
-
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 attemptsapache2-utils
will allow us to configurehtpasswd
credentials for securing your registry
-
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)
-
Add a second firewall configuration by using ufw
ufw default deny incoming
ufw default allow outgoing
ufw limit ssh
ufw allow 5000
- 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
- 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.
- Once your server is configured with Docker and is secured using the UFW + DigitalOcean Firewall, then we can proceed...
- 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 useexample_com
, for help.xyz usehelp_xyz
, etc.
-
Copy the contents of the CSR generated file and paste it into SSLs.com
-
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.
-
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
- 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
- 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
-
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
. -
Save the file.
-
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
- Create your auth directory to store the
htpasswd
inside:
mkdir /root/auth
- Create a username/password for authenticating into your private docker registry:
htpasswd -B -c /root/auth/htpasswd username
- 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.
- Create a new file in
/root
calleddocker-compose.yaml
using:
vi /root/docker-compose.yaml
- 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
- 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 |
- Boot your container
cd /root
docker-compose up -d
- 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
- From your host machine, run the following:
docker login registry.yourdomain.com:5000
Username: username
Password:
Login Succeeded
- 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
- If you're using
docker build
, just make sure your image name is prepended withregistry.yourdomain.com:5000/
before pushing, otherwise it may end up not on your private registry!