arrow_back
Back

Docker reverse proxy: Traefik, Nginx, routing, and TLS

Andrew Dorokhov Andrew Dorokhov schedule 2 min read
menu_book Table of Contents

A reverse proxy server is a server that typically sits in front of other web servers in order to provide additional functionality.

The issue

Docker containers are assigned random IPs and ports which makes addressing them much more complicated from a client perspective. By default, the IPs and ports are private to the host and cannot be accessed externally unless they are bound to the host.

Binding the container to the hosts port can prevent multiple containers from running on the same host. For example, only one container can bind to port 80 at a time. This also complicates rolling out new versions of the container without downtime since the old container must be stopped before the new one is started.

A reverse proxy can help with these issues as well as improve availability by facilitating zero-downtime deployments.

Installation nginx-proxy

There’s a nice solution: open_in_new nginx-proxy .

To start the reverse proxy:

docker container run -d \
      -p 80:80 \
      -v /var/run/docker.sock:/tmp/docker.sock:ro \
      nginxproxy/nginx-proxy

Or using docker-compose.yml:

version: '2'

services:
  reverse-proxy:
    container_name: reverse-proxy
    image: nginxproxy/nginx-proxy
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro

networks:
  default:
    name: reverse-proxy

Attaching new containers

To make our containers work with the reverse proxy, we need to do two things:

  • Expose a port.
  • Set a VIRTUAL_HOST variable.

Example of some container configuration:

version: '2'

services:
  app:
    container_name: dorokhov.codes
    image: dorokhov.codes
    expose:
      - "80"
    environment:
      VIRTUAL_HOST: dorokhov.codes

networks:
  default:
    name: dorokhov.codes

And we have to add our reverse proxy container to the dorokhov.codes network:

docker network connect dorokhov.codes reverse-proxy

Custom Nginx reverse proxy image

For a single upstream (not dynamic Docker discovery), you can build a small image that injects host and upstream via environment variables at startup.

Dockerfile:

FROM nginx:1.7

COPY default.conf /etc/nginx/conf.d/default.conf
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

default.conf:

server {
    listen 80;
    server_name {{NGINX_HOST}};

    location / {
        proxy_pass {{NGINX_PROXY}};
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_redirect off;
        proxy_buffering off;
        proxy_set_header    Host               {{NGINX_HOST}};
        proxy_set_header    X-Real-IP          $remote_addr;
        proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
    }
}

entrypoint.sh:

#!/bin/bash
set -e
sed -i "s|{{NGINX_HOST}}|$NGINX_HOST|;s|{{NGINX_PROXY}}|$NGINX_PROXY|" /etc/nginx/conf.d/default.conf
cat /etc/nginx/conf.d/default.conf
exec "$@"

docker-compose.yml example:

proxy:
  image: proxy:1.0
  links:
    - identidock
  ports:
    - "80:80"
  environment:
    - NGINX_HOST=142.93.71.92
    - NGINX_PROXY=http://identidock:5000
code

Need Help with Development?

Happy to help — reach out via the contacts or go straight to my Upwork profile.

work View Upwork Profile arrow_forward
Next Article

Docker GUI applications: X11, display forwarding, and desktop apps

arrow_forward