Jericho's blog

Setting up nginx as a reverse-proxy for docker services

2020-06-27 13:11:00 +0000

Prerequisites

I'm going to assume that you have a few things already setup before starting.

  • A working server
  • Working nginx setup
  • A service already running in docker

Configuring docker

The main thing you need to do with docker, is make sure that you're exposing any ports that the service needs. Also make sure that none of the ports conflict with other docker services or with any local services.

If you're running docker from the command line than just add something like -p 8080:80 to forward port 8080 on your local machine to port 80 in the docker container.

If you're using docker-compose, then add something like this into your service definition:

ports:
  - "8080:80"

You may also have to configure the service itself to allow proxy connections, but this will depend on exactly what service you're setting up.

Configuring nginx

There's two main ways you may want to address the proxy. You can either use subdomains (the more common and simpler way), or you can use sub-paths (can be more complex to configure).

subdomains

If you're using subdomains, I'd recommend making a new site in nginx. The basic server information will be the same as for your main site, but the special configuration will happen in the location section.

Also, if you are using a subdomain, you will need to add a CNAME record to your DNS server.

server {
        server_name search.jkeyne.dev;

        root /var/www/search;
        index index.html;
        access_log /var/log/nginx/search.access.log;
	   listen 80;

        location / {
                proxy_pass http://localhost:8080/;
                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;
        }
}
  • for server_name set it to subdomain.domain.tld
  • you can set root to anything, as well as index
  • if you want to use something like goaccess, then I'd recommend making a separate access_log per site, if not then ignore that line
  • set listen to whatever port you'll be accessing the server from (port 80 unless you setup SSL)
    • one of the main reasons you may want to proxy into a docker container is that it will be much easier to configure SSL for nginx, and then you're docker service will automatically think it's using SSL
  • under location is where all the special configuration occurs
    • the / means you don't have to type anything after subdomain.domain.tld to access the site
    • change 8080 in proxy_pass to whatever port you told docker to listen to
    • all the proxy_set_header lines you shouldn't need to change. It just passes the client's data to the docker container

Now you should be able to restart nginx, start your docker service, and connect through a browser.

sub-path

This method can be a little bit trickier to properly work, but you don't have to wait for DNS records to propagate so it may be worth it for some situations.

server {
	server_name jkeyne.dev;
	
	root /var/www/html;
	index index.html;
	listen 80;
	
	location ^~ /search/ {
		proxy_pass http://localhost:8080/;
		proxy_http_version 1.1;
		proxy_set_header Connection "upgrade";
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header X-Forwarded-Proto $scheme;
	
		proxy_read_timeout 1d;
	}
}
  • the ^~ /search/ part tells nginx to remove /search/ from the forwarded request
    • without ^~ nginx will essentially redirect to http://localhost:8080/search/
  • this method can be more complicated for some services as you may need to add additional sub-path proxies for them to work (for example bitwarden-rs requires additional sub-path proxies for /notification/hub and /notifications/hub/negotiate)

Now you should be able to restart nginx, start your docker service, and connect through a browser.

end notes

While these instructions will work perfectly for many services, you may need to go to a project's wiki in order to find tailored instructions for getting that project to work with a reverse-proxy.