Programster's Blog

Tutorials focusing on Linux, programming, and open source

Run Your Own Private Docker Registry

Dockerhub is great if your working on content that you are happy to share, but actually, I want to keep 99% of my work private. Thus, I run my own private docker registry and use firewall rules to allow access from only my own IP addresses.


For each of the examples below, simply copy the script into your docker-host server, update the settings (top of the script) and execute it with bash. It will run the registry on port 5000.

Local Storage Setup


###### Fill in the settings below ##################

# Specify the absolute path to where you want to store files

# Give your container a name to recognize it by

########## Don't change below this Line ###########

# stop and remove the existing container if exists
docker kill $CONTAINER_NAME

docker run \
-d \
-v $LOCAL_STORAGE_DIR:/registry \
-e STORAGE_PATH=/registry \
-e SEARCH_BACKEND=sqlalchemy \
-p 5000:5000 \
--name "$CONTAINER_NAME" \

AWS S3 Storage Backend

Create a folder called certs within the folder you store the script below. Within that folder should be the certificate and key provided by a CA.



docker pull $IMAGE_NAME

docker kill $CONTAINER_NAME

docker run \
-e AWS_BUCKET=xxxxxxxxxxxxxxxxxx \
-e STORAGE_PATH=/registry \
-e AWS_KEY="xxxxxxxxxxxxxxxxxx" \
-e AWS_SECRET="xxxxxxxxxxxxxxxxxx" \
-e SEARCH_BACKEND=sqlalchemy \
-v `pwd`/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
-p 5000:5000 \
--restart=always \
--name "$CONTAINER_NAME" \

I got an error message that my certificates were signed by an unrecognised authority when using my StartSSL certificates. I resolved this by appending the to the end of the .crt file's contents.

Securing The Container

If you are not using AWS, and you want to only allow specific IPs to be able to access your registry, then you will need to perform some additional steps with iptables. If you are using AWS, then skip this and just go configure your security groups.

Iptables Example

Create a file called with the contents below.


# clear out all the existing rules and reset
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables --flush

# Now re-add all our rules
/sbin/iptables -A INPUT -i lo -j ACCEPT
/sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow our trusted IPs
iptables -A INPUT -s [your static ip]/32 -p tcp -j ACCEPT

# Allow web traffic to the public (skip this if you are not running a webserver)
iptables -A INPUT -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT

# Allow secure web traffic to the public  (skip this if you are not running a webserver)
iptables -A INPUT -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT

# accept port 500 for our registry
iptables -A INPUT -p tcp --dport 5000 -m state --state NEW,ESTABLISHED -j ACCEPT

# only forward requests on port 5000 if they come from our trusted ips
/sbin/iptables -t nat -A PREROUTING -p tcp --source [static ip]/[cidr] --dport 5000 -j DNAT --to-destination []:5000
/sbin/iptables -t nat -A POSTROUTING -j MASQUERADE

iptables -P INPUT DROP

Now use sudo crontab -e to edit your root crontab and add the following:

@reboot /bin/bash /path/to/

Now your firewall will reset correctly every time your server reboots. If you have any other firewall rules, you will need to add them to that script.

Note: Make sure you have any other firewall programs such as UFW disabled!