0

I am trying to run two React applications and an API server in an EC2 instance and reverse-proxy using NGINX using docker-compose.

When I navigate to example.com, the client app is loaded as expected. However, when I navigate to example.com/admin the admin app is not loaded. The tab name and icon are the ones of the admin app, however the page is completely blank. I am sure it is not the admin app the problem because if I change the proxy_pass directive in the default.conf file for the / location it is loaded as expected. What am I missing then?

Hereafter is the default.conf for NGINX (HTTPS is not implemented yet):

server {
    server_name  www.example.com;
    rewrite ^(.*) http://example.com$1 permanent;
}

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

  root /var/www/html;
  index index.html index.htm index.nginx-debian.html;

  server_name example.com www.example.com;
  
  location / {
    proxy_pass http://client:3000;
  }

  location /admin {
    proxy_pass http://admin:3001;
  }

  location /api {
    proxy_pass http://server:5000;
  }  

  location ~ /.well-known/acme-challenge {
    allow all;
    try_files $uri =404;
    break;
  }
}

Hereafter is the docker-compose.yml file:

version: '3.7'

services:
  client:
    image: app_client
    container_name: client
    restart: unless-stopped
    hostname: client
    ports:
      - '3000:3000'
    networks:
      - network

  admin:
    image: app_admin
    container_name: admin
    restart: unless-stopped
    hostname: admin
    ports:
      - '3001:3001'
    networks:
      - network

  mongodb:
    image: app_mongodb
    container_name: mongodb
    restart: unless-stopped
    hostname: mongodb
    volumes:
      - mongo-data:/data/db
    ports:
      - '27017:27017'
    networks:
      - network

  server:
    image: app_server
    container_name: server
    restart: unless-stopped
    hostname: server
    ports:
      - '5000:5000'
    depends_on:
      - mongodb
    networks:
      - network

  proxy:
    image: app_proxy
    container_name: proxy
    hostname: proxy
    restart: unless-stopped
    ports:
      - '80:80'
      - '443:443'
    volumes:
      - web-root:/var/www/html
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
    depends_on:
      - client
      - server
    networks:
      - network

  certbot:
    ...
networks:
  network:
    driver: bridge

volumes:
  mongo-data:
    driver: local
  certbot-etc:
  certbot-var:
  web-root:
    driver: local
Roberto Rossini
  • 158
  • 2
  • 10
  • Try `location /admin/ { proxy_pass http://admin:3001/; }`. This will strip `/admin` prefix from the URI before it will be passed to the backend, read [this](https://stackoverflow.com/questions/53649885/a-little-confused-about-trailing-slash-behavior-in-nginx) question/answer for more details. – Ivan Shatsky Sep 16 '21 at 09:19
  • Thank you for your answer. However, it has the same blank page behaviour. – Roberto Rossini Sep 16 '21 at 09:36
  • Maybe you need to rebuild your admin app according to your URI prefix, otherwise all links generated by app (routes, assets, etc) won't fall under the `location /admin/ { ... }` thus being served with your client app. Check the [How to deploy a React app to a subdirectory](https://medium.com/@svinkle/how-to-deploy-a-react-app-to-a-subdirectory-f694d46427c1) article to find how to do it. Don't forget to revert changes from my first comment back. – Ivan Shatsky Sep 16 '21 at 10:18
  • Thank you very much, your article solved my problem! I had already added the `basename` in the React Router but it was not enough. Adding the `homepage` field in the `package.json` did the trick! – Roberto Rossini Sep 16 '21 at 11:18
  • Actually, I just realized that in the `default.conf` file I need the following configuration for the `location /admin` in order to let it work: `location ^~ /admin/ { /admin/(.*) /$1 break; http://admin:3001; }` Adding the `homepage` field was not enough. – Roberto Rossini Sep 16 '21 at 11:24
  • Hmm, that sounds strange to me. I thought you don't need to change an URI when your React app is set up to use an URI prefix. And if it is really needs to being changed, can you try location block from my first comment? It should do the same while being slightly more performant (no regex usage). – Ivan Shatsky Sep 16 '21 at 11:30
  • I tried both of them with the `homapage` field. However, none of them worked. I am a beginner in NGINX so I do not really know why it works with this configuration and not in the ones you suggested. – Roberto Rossini Sep 16 '21 at 11:57

1 Answers1

0

try this:

location ^~ /admin/ {
    rewrite /admin/(.*) /$1 break;
    proxy_pass http://0.0.0.0:3001;
}
Roberto Rossini
  • 158
  • 2
  • 10
hakik ayoub
  • 55
  • 1
  • 7
  • Thank you for your commet. However, using `http//:0:0:0:0:3001` returns a "502 Bad Gateway". Instead, changing `http//:0:0:0:0:3001` to `http://admin:3001` has the same blank page behaviour. – Roberto Rossini Sep 16 '21 at 09:21
  • in the proxy_pass use what works for you in curl, example: if curl http://admin:3001 works fine then, proxy_pass should work just fine. Otherwise, check your code – hakik ayoub Sep 16 '21 at 10:16
  • `admin:3001` works fine if inside `location / {}`. However, if in `location /admin {}` it does not. – Roberto Rossini Sep 16 '21 at 10:20
  • please test this code as it is: location ^~ /admin/ { rewrite /admin/(.*) /$1 break; proxy_pass http://admin:3001/; } – hakik ayoub Sep 16 '21 at 10:23
  • This code gave me `nginx: [emerg] invalid URL prefix in /etc/nginx/conf.d/default.conf:28`. In the end, adding the `homepage` field in `package.json` of the **admin** app did the trick. Thank you anyways! – Roberto Rossini Sep 16 '21 at 11:08