Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular App running on nginx and behind an additional nginx reverse proxy

I'm currently trying to create a reverse proxy for two Angular apps. I want the apps to be both accessible through the 443 port of the docker host with SSL enabled (like https://192.168.x.x/app1 and https://192.168.x.x/app2), so that the users don't have to type in the port numbers for each app.

My setting is, that every part of the application runs within its own Docker container: - Container 1: Angular App 1 (Port 80 exposed to host on port 8080) - Container 2: Angular App 2 (Port 80 exposed to host on port Port 8081) - Container 3: Reverse Proxy (Port 443 exposed)

Both Angular apps and the reverse proxy are running on nginx. The apps are build like that: ng build --prod --base-href /app1/ --deploy-url /app1/

The nginx setting of the apps is like that:

server {
  listen 80;
  sendfile on;

  default_type application/octet-stream;

  gzip on;
  gzip_http_version 1.1;
  gzip_disable      "MSIE [1-6]\.";
  gzip_min_length   256;
  gzip_vary         on;
  gzip_proxied      expired no-cache no-store private auth;
  gzip_types        text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  gzip_comp_level   9;

  root /usr/share/nginx/html;

  index index.html index.htm;

  location / {
    try_files $uri $uri/ /index.html =404;
  }
}

The nginx configuration of the reverse proxy is like that:

server {
  listen 443;
  ssl on;
  ssl_certificate /etc/nginx/certs/domaincertificate.cer;
  ssl_certificate_key /etc/nginx/certs/domain.key;

  location /app1/ {
    proxy_pass http://192.168.x.x:8080;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto  $scheme;
    proxy_http_version 1.1;
    proxy_cache_bypass $http_upgrade;

  }
  location /app2/ {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_cache_bypass $http_upgrade;
     proxy_pass http://192.168.x.x:8081;
  }
}

If I try to open the app on the url 'https://192.168.x.x/app1', the app is reached, but I get error messages for all static files 'Uncaught SyntaxError: Unexpected token <': Errormessages from chrome

It seems, that instead of the static js and css files, the index.html of the app is returned. I believe that this is a problem of the nginx config of the apps themselves.

I have spent quite a time trying to figure out how to solve that problem, but no luck yet. I hope that someone here can help me with that.

like image 281
Daniel Ostheimer Avatar asked Sep 12 '18 08:09

Daniel Ostheimer


2 Answers

Firstly I prefer the approach one service, one container providing redirection with nginx. It also covers almost automatically https using a dockerized nginx reverse proxy with certificates. You can also use letsencrypt certificates if you want. You can deploy your Angular applications into containers behind the reverse proxy.

enter image description here

Below I describe the steps for your docker deployment. I also include portainer which is a GUI for your container deployment:

  • Run the nginx in the port 443 sharing the certificates generated for your.domain using the option -v $HOME/certs:/etc/nginx/certs. Put the certificates somewhere on the host for instance /etc/nginx/certs. Option --restart=always is needed to automatically run the container when the server reboot:
docker run -d --name nginx-proxy --restart=always -p 443:443 -v /root/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
  • Your app 1 and 2 should be deployed in appX.yourdomain and must be redirected to the docker IP (this way nginx can redirect the subdomain to your container).
  • Dockerfile MUST expose the web service in different ports (8080 and 8081). The component should be also deployed on that port
  • The most important thing is that application 1 and 2 containers must include the option -e VIRTUAL_HOST=appX.yourdomain and PROXY_ADDRESS_FORWARDING=true:
docker run --name app1 --restart=always -d -e PROXY_ADDRESS_FORWARDING=true -e VIRTUAL_HOST=app1.yourdomain yourcontainer
  • Portainer is also launched to provide the dashboard for the docker containers:
docker run --name portainer --restart=always -v ~/portainer:/data -d -e PROXY_ADDRESS_FORWARDING=true -e VIRTUAL_HOST=portainer.yourdomain portainer/portainer -H tcp://yourdockerip:2376

So basically when some request (subdomain) arrives to nginx, it automatically redirects to the angular container app (referenced by appX.yourdomain). The best thing is that jwilder/nginx-proxy automatically update the nginx.conf when the different containers start. Our microservices architecture are implemented in Spring (autodeployment) so I include here how you can build the container with angular and nginx, but I guess you already solved this. I would also consider to use docker-compose.

like image 124
Carlos Cavero Avatar answered Nov 12 '22 18:11

Carlos Cavero


the problem is: 8080 and 8081 containers can open resources like localhost:8080/styles.css or localhost:8080/bundle.js. but with current configuration they get localhost:8080/app1/styles.css requests instead. try adding rewrite /?app1/(.*)$ /$1 break; rule to reverse proxy, so they would get right requests

like image 5
Andrei Avatar answered Nov 12 '22 17:11

Andrei