Nginx Reverse Proxy for your Docker Registry
Part 2 of Setting up a Docker Registry
Who is tired of typing :5000 every time you push or pull something from your private registry? Since everyone is raising their hands and several of you are screaming in fits of rage, I'm going to tell you a really quick way to set up Nginx to reverse proxy our traffic from port 80 and 443 to 5000.
Nginx?
Nginx (pronounced "engine x") is a web server with a strong focus on high concurrency, performance and low memory usage. It can also act as a reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer and an HTTP cache. It also has an official image maintained in the Docker hub and all the cool kids are doing it.
Log in to your registry server and pull down the official nginx image.
a578992@vc2coma2067822n:~$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
7a42f1433a16: Pull complete
3d88cbf54477: Pull complete
fbdef4a4ff6b: Pull complete
067439a15e7d: Pull complete
24c1dc27266b: Pull complete
1acf3046c96d: Pull complete
3298e91823c1: Pull complete
15340d6ed415: Pull complete
06908a7ce444: Pull complete
fc68e18b17d8: Pull complete
0b9b1560f5e9: Pull complete
52d0c47f4ca7: Pull complete
Digest: sha256:44e64351e39e67b07799a1ce448cef33aaa88daedbbb5f427fac4eeafe3e148f
Status: Downloaded newer image for nginx:latest
a578992@vc2coma2067822n:~$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
nginx latest 52d0c47f4ca7 13 days ago 132.9 MB
registry 2 2eafecf5086b 2 weeks ago 220.7 MB
According to the Nginx README we sould just be able to:
$ docker run --name some-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx
That doesn't really help us all that much since the default nginx config is kind of bland. Here is my site config.
a578992@vc2coma1066091n:/docker/nginx
> cat reg.johnray.io.conf
# Define Upstream
upstream registry {
server reg:5000;
}
# http redirects to https
server {
listen 80;
server_name reg.johnray.io;
# Strict Transport Security
add_header Strict-Transport-Security max-age=2592000;
rewrite ^/.*$ https://$host$request_uri? permanent;
}
server {
listen 443;
server_name reg.johnray.io;
client_max_body_size 0; # Disabled to prevent 413's
ssl_certificate /etc/nginx/certs/docker-registry-v2.crt;
ssl_certificate_key /etc/nginx/certs/docker-registry-v2.key;
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/registry.access.log;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Fix the “It appears that your reverse proxy set up is broken" error.
proxy_pass https://registry;
proxy_read_timeout 90;
}
}
This is pretty barebones and essentially redirects port 80 to 443 and then on to 5000. In the upstream section you will see that I call my server reg:5000
. We will talk about how that works when we launch the container. To make things easy you can copy paste this config. Everywhere you see reg.johnray.io
you should insert your registry name. reg.johnray.io doesn't exists and even if it did it wouldn't help you to try and reverse proxy sommone else's registry.
Save your config somewhere, mine is in /docker/nginx/reg.johnray.io.conf, and let's get to launching the container.
3..2..1..Launch
If you followed my previous post you will already have some ssl certs so let's use those. They should be somewhere like /docker/certs.
Launch your container like so.
$ docker run -d --restart=always --name nginx -v /docker/nginx/reg.johnray.io.conf:/etc/nginx/conf.d/default.conf -v /docker/certs:/etc/nginx/certs -p 80:80 -p 443:443 --link registry:reg nginx
So we are launching a container with a restart polocy of always, just in case it crashes, a name of nginx, some volume mounts for our default config (I'm just overwritting the default here instead of trying to have multiple sites) and our SSL certificates, we are mapping some ports, and finally we are likning our registry container. That's the magic that makes the reg:5000
entry work in the reg.johnray.io.conf file.
Once this is up and running test it by tagging one of your localhost images.
docker tag reg.johnray.io:5000/docker-chrome reg.johnray.io/docker-chrome
docker push reg.johnray.io/docker-chrome
If all goes well your image should now happily push to your registry server. Better yet any Docker host that trusts your self signed cert, or your real cert if you have one, will be able to push to your registry without :5000.
Happy Hacking!
You might also be interested in these articles...