3

My Goal

I want to use a single NGinx docker container as a proxy.

I want it to respond to traffic on my domain: "sub.domain.com" and listen on port 80 and 443.

When traffic comes in on /admin I want it to direct all traffic to one docker container (say... admin_container:6000).

When traffic comes in on /api I want it to direct all traffic to another docker container (say... api_container:5500).

When traffic comes in on any other path (/anything_else) I want it to direct all traffic to another docker container (say... website_container:5000).

Some Helpful Context

Real quick, let me provide some context in case it's helpful. I have a NodeJS website running in a docker container. I'd like to also have an Admin section, created with ASP.NET Core that runs in a second docker container. I'd like both of these websites to share and make use of a single ASP.NET Core Web Api project, running in a third docker container. So, one NodeJS project and two ASP.NET Core projects, that all live on a single subdomain:

  • sub.domain.com/
    • Serves the main website
  • sub.domain.com/admin
    • Serves the Admin website
  • sub.domain.com/api
    • Serves API endpoints and handles Database connectivity

What I have So Far

So far I have the NGinX reverse proxy set up and a single docker container for the NodeJS application. Currently all traffic on :80 is redirected to 443. All traffic on 443 is directed to the NodeJS docker container, running privately on :5000. I'll admit I'm not great with NGinx and don't fully understand how this works.

The NGinx.conf file

worker_processes 2;

events { worker_connections 1024; }

http {
    sendfile on;
    proxy_buffer_size   128k;
    proxy_buffers   4 256k;
    proxy_busy_buffers_size   256k;

    upstream docker-nodejs {
        server nodejs_prod:5000;
    }

    server {
        listen 80;
        server_name sub.domain.com;
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl;
        server_name sub.domain.com;
        ssl_certificate     /etc/nginx/ssl/combined.crt;
        ssl_certificate_key /etc/nginx/ssl/mysecretkeyfile.key;

        location / {
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Forwarded-Proto https;
            proxy_set_header   X-Forwarded-Ssl on;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
            proxy_pass         http://docker-nodejs;
        }
    }

}

Quick Note: In the above code "nodejs_prod:5000" refers to the container who's name is "nodejs_prod" and listens on port 5000. I don't understand how that works, but it is working. Somehow docker is creating DNS entries in the private network, one for each container name. I'm actually using docker-compose.

My Actual Question: How will this NGinx.conf file look when I have 2 more websites (each a docker container). It's important that /admin and /api are sent to the correct docker containers, and not handled by the "catch all" location. I'm imagining that I'll have a "catch all" location which captures all traffic that DOESN'T START WITH /admin OR /api.

Thank you!

Captainlonate
  • 4,878
  • 4
  • 25
  • 35

1 Answers1

2

In your nginx config you want to add location rules, such as

  location /admin {
    proxy_pass http://admin_container:6000/;
  }

  location /api {
    proxy_pass http://api_container:5500/;
  }

This redirects /admin to admin_container port 6000, and /api to api_container and port 5500.

docker-compose creates a network between all it's containers. Which is why http://api_container:5500/ points to the container named api_container and the port 5500. This can be used for communication between containers. You can read more about it here https://docs.docker.com/compose/networking/

SebastiaanYN
  • 546
  • 6
  • 12
  • 1)) What stops "location / {}" from handling the request, rather than the other two. Meaning, won't "location / {}" just catch all requests before /admin and /api have a chance to? Does order matter maybe? 2)) Do I just add these two within the second "server" section? Do I need a separate "server" section per location? – Captainlonate Mar 31 '19 at 20:54
  • 1) nginx handles this almost entirely. It will look for the most specific prefix, so anything that starts with `/admin` will be handled by the `/admin` location. 2) You put them in the same server section. The server section can have multiple location sections. – SebastiaanYN Mar 31 '19 at 20:59