'Expose multiple api uri on the same nginx server block

Goal

My goal is to setup multiple backend api container exposed on the same nginx server :

  • http://localhost:80/api/account -> call http://account-service:9000/
  • http://localhost:80/api/cart -> call http://cart-service:9000/
  • http://localhost:80/api/order -> call http://order-service:9000/
  • http://localhost:80/api/product -> call http://product-service:9000/
  • ...

My backend container are based on php:7.2-fpm (symfony hosted on every apache container) and they don't have any route called api/${NAME_SERVICE} (i don't want to create some useless parent route in my backends).

So, my request is simple, i want that when i call for example :

  • http://localhost:80/api/account/profile

That my backend account container serve this uri :

  • http://account-service:9000/profile

What i tried so far

  • rewrite (doesn't help with fastcgi params)
  • setting up an upstream server with proxy_pass
  • tweaking fastcgi_param REQUEST_URI (without any success)
  • alias (forbidden access)

Conf

Here is my nginx.conf :

...
server {
        server_name ~.*;
        client_max_body_size 50m;

        location / {
            try_files $uri /index.php$is_args$args;
        }
        # work if i want to serve account-service on http://localhost:80/
        # location ~ ^/index\.php(/|$) {
        #     fastcgi_pass account-service:9000;
        #     fastcgi_buffers 16 16k;
        #     fastcgi_buffer_size 32k;
        #     fastcgi_param SCRIPT_FILENAME /usr/src/app/public/index.php;
        #     include fastcgi_params;
        # }

        # my last attempt with alias
        location ~* ^/api/account {
            alias /;
            index index.php;
            
            location ~ index\.php(/|$) {
                fastcgi_pass account-service:9000;
                fastcgi_buffers 16 16k;
                fastcgi_buffer_size 32k;
                fastcgi_param SCRIPT_FILENAME /usr/src/app/public/index.php;
                fastcgi_intercept_errors on;
                include fastcgi_params;
            }
        }
}
...

docker-compose.yml :

  nginx:
    image: nginx:1.15.3-alpine
    restart: on-failure
    volumes:
      - "./build/nginx/default.conf:/etc/nginx/nginx.conf:ro"
      - "./logs/nginx:/var/log/nginx"
    ports:
      - "80:80"
    depends_on:
      - account-service
      - account-db
      - cart-service
      - cart-db
      - order-service
      - order-db
      - product-service
      - product-db

  account-service:
    env_file:
      - config/account.env
    build: apps/account-service
    restart: on-failure
    expose:
      - "9000"
    volumes:
      - "./apps/account-service:/usr/src/app"
    depends_on:
      - account-db

  cart-service:
     ...

P.S: I known that you can split nginx conf into multiple server blocks that listen on different port/hostname, but that's not what i want to achieve here.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source