Search code examples
dockernginxdocker-composereverse-proxy

How to NGINX Reverse Proxy outside of Docker to proxy_pass to docker containers


I have an NGINX running on a CentOS server and would like to proxy_pass to running docker containers running on the same host.

When using proxy_pass with the IP of container it works, however if machine gets rebooted sometimes the IP changes of the container and have to manually edit the nginx.conf to re-point to new ip of Container. I know that NGINX can be setup inside of its own docker container and linked to other running containers but that would take a long time to setup and test.

Is there a way to use somehow container name or another identifier that does not change directly on the host's NGINX?


Solution

  • I know that NGINX can be setup inside of its own docker container and linked to other running containers but that would take a long time to setup and test.

    Short answer

    If you don't want to run nginx in it's own container, you can create a docker network with a fixed IP range:

    docker network create --driver=bridge --subnet=192.168.100.0/24 nginx.docker
    

    And start your container with a fixed IP

    docker run --net nginx.docker --ip 192.168.100.1 ...
    

    See docker network create and Assign static IP to Docker container

    Long answer

    But I would still suggest to run nginx in a container as well, then docker will take care of the DNS resolution and routing. It's actually quickly done and pretty straight forward. You can either define all services in one docker-compose.yml and make sure they all share the same network or:

    1. Create a docker network with docker network create nginx.docker
    2. Add the network to the docker-compose.yml files of your services
    3. Adjust your nginx.conf

    For example:

    nginx

    The docker-compose.yml of nginx

    services:
    nginx:
      image: nginx:alpine
      container_name: nginx
      ports:
        - "80:80"
        - "443:443"
      volumes:
        - type: bind
          source: ./nginx.conf
          target: /etc/nginx/nginx.conf
      networks:
        - nginx.docker
    
    networks:
      nginx.docker:
        name: nginx.docker
        external: true
    

    Note that "80:80" will bind to all interfaces, use the IP of an interface, e.g. "192.168.0.1:80:80" to bind to one specific interface only.

    Your service container

    docker-compose.yml

    services:
    my_service:
      image: image_name
      container_name: myservice
      networks:
        - nginx.docker
    
    networks:
      nginx.docker:
        name: nginx.docker
        external: true
    

    nginx config

    An in the server section of your nginx.conf:

    server {
    listen 443 ssl;
    server_name your.server.name;
    
    # Docker DNS
    resolver 127.0.0.11;
    set $upstream_server http://myservice:8080;          # or myservice.nginx.docker
    
      location  / {
         proxy_pass $upstream_server;
    
         # further proxy config ...
      }
    }
    

    Note the resolver 127.0.0.11 explicitly telling nginx to use the docker DNS. Not sure if it is still needed, but I had problems before, when not using it.