Sergey Petrushin
Sergey Petrushin

Reputation: 11

Nginx proxy with multiple locations for a single domain

Nginx is acting as frontend for 2 docker containers with Node.JS under single domain configuration (domain name: url.domain)

container1 = should receive everything from / and assets from assets-1 directory (http://url.domain -> http://container1)

container2 = should receiver evertythng from different urls, fex /login, /logout, etc and assets from assets-2 directory (http://url.domain/login -> http://container2/login

With the following configuration I was able to get proper pages, etc, but not assets:

location  / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    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_pass_header Set-Cookie;
    proxy_redirect off;
    proxy_read_timeout 30m;
    proxy_connect_timeout 30m;
    proxy_pass http://container1;
}
location ~ ^/(login|logout)(/)?(.*) {
    client_max_body_size 128M;
    proxy_redirect off;
    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 Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_pass_header Set-Cookie;
    proxy_http_version 1.1;
    proxy_read_timeout 30m;
    proxy_connect_timeout 30m;
    proxy_pass http://container2;
}

After some changes and attempts, I was able to get everything running using the following configuration:

location = / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    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_pass_header Set-Cookie;
    proxy_redirect off;
    proxy_read_timeout 30m;
    proxy_connect_timeout 30m;
    proxy_pass http://container1;
}
location  / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    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_pass_header Set-Cookie;
    proxy_redirect off;
    proxy_read_timeout 30m;
    proxy_connect_timeout 30m;
    proxy_pass http://container2;
}
location ^~ /assets-1 {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    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_pass_header Set-Cookie;
    proxy_redirect off;
    proxy_read_timeout 30m;
    proxy_connect_timeout 30m;
    proxy_pass http://container1;
}
location ~ ^/(login|logout)(/)?(.*) {
    client_max_body_size 128M;
    proxy_redirect off;
    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 Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_pass_header Set-Cookie;
    proxy_http_version 1.1;
    proxy_read_timeout 30m;
    proxy_connect_timeout 30m;
    proxy_pass http://container2;
}

I'm sure that this isn't the best way. Any suggestions or improvements?

Upvotes: 1

Views: 1044

Answers (1)

Ivan Milisavljevic
Ivan Milisavljevic

Reputation: 2068

You will have a lot of issues when you decide to scale up, I would suggest you to switch to something more dynamic. I would do it this way:

  1. Have a public facing proxy NGINX container bound to your local ip
  2. Internal NGINX container serving only your assets (assets.domain.com) exposing only needed port
  3. Internal NGINX container serving only your website (domain.com/www.domain.com) exposing only needed port

To achive something like this you can:

First

Configure proxy. There is this awesome Nginx proxy container which supports service discovery (It will detect if you started/stoped container with publicly exposed ports and generate new proxy configuration for you). Simple example would be something like this:

version: '2'

services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro

  assets:
    image: me/assets
    environment:
      - VIRTUAL_HOST=assets.mydomain.com
      - VIRTUAL_PORT=80

  webiste:
    image: me/website
    environment:
      - VIRTUAL_HOST= mydomain.com, www.mydomain.com
      - VIRTUAL_PORT=80

Second

Create 2 different containers (one for webiste, one for assets) with webserver configuration specific to the container (Note: You dont have to use NGINX as your downstream web-server you can use what ever you like) As a bonus you can create some advanced caching mechanism for your assets container


This approach will help you in multiple situations like if you want to scale your webiste serving container to multiple instances, have centralized logging or ssl termination, fail-over, A/B testing etc, it also gives you the opportunity to split your concerns in 2 smaller containers which will improve maintainability and scalability of your stack (If in some point you decide to go worldwide you can deploy just your assets or just webiste containers around the world, without a need to deploy entire stack)

Upvotes: 1

Related Questions