[Fixed] Nginx reverse proxy + Angular served by Nginx

Issue

I have an angular app, my-app, which I build locally with ng build --prod and serve with Nginx dockerized, the Dockerfile is:

FROM nginx:alpine
COPY /dist/my-app /usr/share/nginx/html
EXPOSE 80

As long as I launch a container based on an image build with this Dockerfile, it works.
Though, I need to put another Nginx acting as a reverse proxy before this one, I want to redirect the traffic with a route like /my-app to the internal Nginx serving Angular, like so:

http://DOMAIN/my-app ---> Reverse Proxy ---> Nginx+Angular

I’ll use Docker Compose for local dev. My docker-compose.yml is very simple:

version: '3'

services:
    nginx:
        container_name: my-nginx
        build: ./nginx
        ports:
            - "80:80"
    my-app:
        container_name: my-app
        build: ./my-app

For the Angular app, I redefine "baseHref": "./my-app/" in my angular.json file, I build again and I configure the reverse proxy as follows:

events {}

http {

  server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root                /var/www;
    index               index.html;

    location / {
        index           index.html;
    }

    location /my-app {
      rewrite                     /my-app/(.*) /$1 break;
      proxy_pass                  http://my-app:80;
      proxy_set_header Host       $host;
      proxy_set_header Upgrade    $http_upgrade;
      proxy_set_header Connection $http_connection;
      proxy_set_header Host       $host;
    }
  }
}

Here, the index.html in the location / directive is a custom one, not the Angular app’s one. Thus, I expect my reverse proxy to serve the index.html when visiting the route /, which it does, but I get a 400 Bad Request error when I try to visit /my-app/.
Does someone have a solution for this? What am I getting wrong? Thanks!

Solution

Just guessing. I would do it that way.

    # Maybe not necessary to redirect from /my-app to /my-app/.
    location ~ ^/my-app$ {
      set $myargs $args;  # workaround to encode spaces in query string!
      return 303 $scheme://$server_name/my-app/$is_args$myargs;
    }

    location /my-app/ {  # works mostly with and sometimes without slash at end!
      proxy_pass                  http://my-app:80/;  # slash at end is goddamn important here; it hides /my-app/ and does all the $request_uri or regex, $is_args and $args magic for you!
      proxy_set_header Host       $host;
      proxy_set_header Upgrade    $http_upgrade;
      proxy_set_header Connection $http_connection;
      proxy_set_header Host       $host;
    }

If your back end sends redirects you are maybe screwed. Check with curl -IL http://my-app. If you see 301, 302, 303 up to 308 with a target Location: – it’s a redirect. But maybe my other answer there can help (rewrite redirects): https://serverfault.com/a/986034/304842 or try proxy_redirect. The problem that I seeing is that you want websockets!? Maybe you need sub_filter or subs_filter too, to remove /my-app/ from source code for other links and resources. Check with [F12] -> Network in your browser.

Leave a Reply

(*) Required, Your email will not be published