I am trying to use Nginx as a reverse proxy for a few backends. It's probably not relevant, but the backends are all hosted within a single Docker network, and the network is being created using docker-compose
.
The backends all have the same endpoints that need to be exposed, so to reduce duplicate configuration lines I am trying to use map
.
map $http_host $backend {
host-a.example.com host-a;
host-b.example.com host-b;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name _;
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/key.pem;
location / {
# there is no DNS resolution if we set proxy_pass targets dynamically,
# use the docker internal DNS server
resolver 127.0.0.11;
proxy_pass "http://$backend:8080/";
proxy_http_version 1.1;
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-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The resolver
line has been added as Nginx will otherwise give the error: no resolver defined to resolve *hostname*
However with this configuration I am finding that requests are being sent to the wrong path, for example if I send a request to https://host-a.example.com/books
or https://host-a.example.com/books/123/front-cover.jpg
the page that is returned is always the root of the site (i.e. https://host-a.example.com/
), it seems that for some reason proxy_pass is not including the path with the request to the backend server.
Is there a way that I can make this work with map
or do I need to create a separate server
block for each of the backends that I want to proxy requests to.
CodePudding user response:
From the proxy_pass
documentation:
When variables are used in proxy_pass
. . .
In this case, if URI is specified in the directive, it is passed to the server as is, replacing the original request URI.
You should either remove the trailing /
(the documentation calls this the optional URI) :
proxy_pass http://$backend:8080;
Or provide the full URL of the request (conveniently available as a built-in variable) :
proxy_pass http://$backend:8080$request_uri;