简体   繁体   中英

Nginx rewrite to subfolder under root

I have a few microservices manged by docker running in a backend private network and want to set up a dynamic routing managed by nginx so that it would choose the microservice based on the URI. I've got three questions:

  1. I need nginx to take the domain name for the fastcgi_pass directive from the first segment of the path in the URI, so "app" from the statement fastcgi_pass app:9000; should come from here: https://example.com/app/foo/bar . If the URI was https://example.com/another-app/foo/bar in the URI, the directive would look like fastcgi_pass another-app:9000; Is it possible this way dynamically, or I'll have to create a separate location for every FastCGI server?

  2. I also need it to rewrite to a folder under the root depending on the same first URI path's segment. I wrote a config but getting 404 errors. I'm a newbie to nginx and just noticed that the paths in the nginx and php-fpm containers don't match. Can the 404 errors be related to this fact?

  3. Is this kind of routing possible at all (see the config below for more details)? Another option is to create a separate location for every microservice, but I don't want to change this config every time I add or remove a microservices.

Here is my config:

server {
    server_name _;
    root /services;

    #rewrite to the subfolder under root depending on the first section in the path
    rewrite ^/(\w+)(/|$) /$1/app_dev.php$is_args$args last;

    location / {
        # try to serve file directly, fallback to app.php
         try_files $uri /app_dev.php$is_args$args;
    }

    location ~ ^/(\w+)/(app_dev|config)\.php(/|$) {
    #further rewrite to the /web subfolder with the front controller
        rewrite ^/(\w+)/(app_dev|config)\.php(/|$) /$1/web/$2.php$is_args$args break;

        fastcgi_pass media:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
    }

    location ~ \.php$ {
        return 404;
    }

    error_log  /var/log/nginx/error.log notice;
    access_log /var/log/nginx/access.log;
    rewrite_log on;
}

Here is the log:

backend_1   | 2017/09/17 20:03:54 [error] 8#8: *1 open() "/usr/share/nginx/html/media" failed (2: No such file or directory), client: 172.25.0.1, server: localhost, request: "GET /media HTTP/1.1", host: "localhost:8082"
backend_1   | 172.25.0.1 - - [17/Sep/2017:20:03:54 +0000] "GET /media HTTP/1.1" 404 571 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36" "-"

One more issue is that I don't see any rewrite logs, guessing it might have been related to the fact that neither of the locations match.

So this is possible in a single location block itself

location ~ ^/(?P<app>\w+)/(app_dev|config)\.php(/|$) {
#further rewrite to the /web subfolder with the front controller
    rewrite ^/(\w+)/(app_dev|config)\.php(/|$) /$1/web/$2.php$is_args$args break;

    fastcgi_pass $app:9000;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;

    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    fastcgi_param DOCUMENT_ROOT $realpath_root;
}

I've come up with the following nginx config allowing to route requests to apps in different docker containers. Thanks @TarunLalwani for the hint:

server {
    server_name _;

    location ~ ^/(?P<service>\w+)(/|$) {
        root /services/$service/web;

        rewrite ^ /app_dev.php$is_args$args break;

        resolver 127.0.0.11;
        fastcgi_pass $service:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME /app/web/app_dev.php;
        fastcgi_param DOCUMENT_ROOT /app/web;
    }

    location ~ \.php$ {
        return 404;
    }

    error_log  /var/log/nginx/error.log debug;
    access_log /var/log/nginx/access.log;
    rewrite_log on;
}

The application routes also need a prefix matching to the name of the microservice, I've added it in the file app/config/routing.yml (I'm using Symfony):

app:
    resource: '@AppBundle/Controller/'
    type: annotation
    prefix: /media

The code of the microservices is mounted to the nginx container under the /services directory from the apps' containers. The absolute paths in the nginx container and the apps' containers don't match, so it's mapped using fastcgi params.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM