Nginx Proxy

The jwilder/nginx-proxy container is a great way to automatically manage easy access to various other docker containers on the same network. It also provides a simple way to generate and renew Let's Encrypt certificates for any container that is internet-facing.

Using docker compose, getting set up with HTTPS is trivial. The following is an annotated example of how it would all hang together.

version: '3.2'
services:
  proxy:
    image: jwilder/nginx-proxy:alpine
    restart: always
    # The proxy will be the only container running on port 80 and 443. This is
    # to ensure that we can access any service via the browser without having
    # to specify any ports.
    ports:
      - '80:80'
      - '443:443'
    volumes:
      # Add custom nginx config to the ./nginx/proxy.conf file. This is useful
      # for disabling version numbers or increasing the maximum file size for
      # uploading files.
      - './nginx/proxy.conf:/etc/nginx/conf.d/proxy.conf:ro'

      # This is where the magic happens. The proxy container watches the
      # docker socket for any changes to containers and inspects their
      # environment variable to set up vhost entries for. Make sure this is a
      # read only mount.
      - '/var/run/docker.sock:/tmp/docker.sock:ro'

      # The following 3 mounts allow the nginx process read and set up vhost
      # entries that the Let's Encrypt companion container has generated for us.
      # In the next service definition we see how this hooks up.
      - './nginx/vhost.d:/etc/nginx/vhost.d'
      - './nginx/html:/usr/share/nginx/html'
      - './nginx/certs:/etc/nginx/certs'
    # This label is required as the Let's Encrypt companion container needs to
    # identify which container the nginx proxy is running in.
    labels:
      - com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy

  proxy_letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    restart: always
    # When setting up new SSL enabled domains, it's useful to have a testing
    # environment before rolling out fully fledged SSL certificates for your
    # service. Setting the `ACME_CA_URI` environment variable to the below URL
    # allows for multiple attempts at certificate generation. Once this
    # container is generating certificates, comment this line out and recreate
    # the container.
    environment:
      ACME_CA_URI: https://acme-staging.api.letsencrypt.org/directory
    volumes:
      # Similar to the main proxy container, this one also needs to watch the
      # docker socker to know when certification generation should occur. Make
      # sure this is a read only mount.
      - '/var/run/docker.sock:/var/run/docker.sock:ro'

      # As noted above, these mounts should be the same as the main nginx
      # container. This is where Let's Encrypt certificates are saved so the
      # main container can read and configure the vhosts appropriately.
      - './nginx/vhost.d:/etc/nginx/vhost.d'
      - './nginx/html:/usr/share/nginx/html'
      - './nginx/certs:/etc/nginx/certs'

    # This is more of a convenience configuration to make sure that the proxy
    # container is running when starting up the Let's Encrypt one.
    depends_on: ['proxy']

The next step is to create appropriate environment variables and host records to map your containers to the proxy. This is done by creating VIRTUAL_HOST, VIRTUAL_PORT, LETSENCRYPT_HOST, and LETSENCRYPT_EMAIL environment variables.

version: '3.2'
services:
  proxy:
  # ...snip...

  my_new_service:
    # ...snip...
    environment:
      # The `VIRTUAL_HOST` environment variable specified the vhost names to be
      # generated by the proxy. Here we're telling the proxy to forward both
      # my.service.home and my.domain.com to the my_new_service container
      VIRTUAL_HOST: my.service.home,my.domain.com

      # Sometimes containers may not specify (EXPOSE) which port their software
      # is running on. If necessary, use `VIRTUAL_PORT` to amend this.
      VIRTUAL_PORT: 8080

      # The following 2 environment variables are required for the generation of
      # Let's Encrypt SSL certificates. Note that the `LETSENCRYPT_HOST`
      # **must** be specified in the `VIRTUAL_HOST` environment variable for
      # forwarding to be successful.
      # It's also worth noting that the current version of this container must
      # be accessible over the internet on both port 80 and 443. So check with
      # your ISP and router settings that these ports are unblocked and open.
      LETSENCRYPT_HOST: my.domain.com
      LETSENCRYPT_EMAIL: [email protected]

Content properties

  • Type: Note
  • Category: Self Hosting
  • Tags: ops
  • Custom slug: None

This is a preview of a simpler page design that I'm working on over the next little bit. I've finally added a (click it!) but there's still a few pages left to be converted so don't worry if things don't look quite right just yet πŸ™

Content on blog pages use the CC-BY-SA license. The source code and notes use the MIT license. Unsure? Mention me on Mastodon.