I have this nginx.conf configuration file inherited from a github project and i’d like some people to explain me what is doing what:
upstream hello_django {
server web:8000;
}
server {
listen 80;
server_name react-wagtail-api.accordbox.com;
location / {
proxy_pass http://hello_django;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
client_max_body_size 20M;
}
location /static/ {
alias /app/static/;
}
location /media/ {
alias /app/media/;
}
}
server {
listen 80;
server_name react-wagtail.accordbox.com;
location / {
root /usr/share/nginx/html/build;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
with
upstream hello_django {
server web:8000;
}
is web
a service (elswhere there is a docker-compose container name which is web
… is it a ref to that? ) ?
What does upstream
define exactly?
with
server_name react-wagtail-api.accordbox.com;
what happens if i dont define a server_name
for example in case i dont have yet a domain? is server_name the domain typed in the adress bar of the browser? can i define it as the local ip and let my domain name provider do the redirect? can i define it as the internet ip of the server and let my domain name provider do the redirect?
As there are two servers on the same port, can i define for example server_name my_internet_ip/app1
and server_name my_internet_ip/app2
to serve two servers on port 80?
2
Answers
web
service in your case resolves to some IP, same withserver_name
. You can read more about upstreams here, same for server_name directive.Generally,
web
here is an upstream domain name (can be also specified via IP address or UNIX socket path). However, when this is executed within the docker-compose context, at the nginx startup time it will be resolved to theweb
container internal IP using docker internal domain name resolving system.For this particular configuration, there will be no difference using either
or specifying an upstream address directly in the
proxy_pass
directive:Really useful
upstream
use cases include failover (example) or load balancing (example). Read thengx_http_upstream_module
documentation to find out all the available features.To understand this part make sure you read the following two chapters from the official documentation:
You can omit the
server_name
directive from the server block at all. For any HTTP request arriving at the TCP port where nginx is listening, one of the definedserver
blocks (usually the very first one appearing in the configuration, unless being specified explicitly usingdefault_server
parameter oflisten
directive) will act as the default server if more appropriate server block won’t be found. TheHost
HTTP request header value is used to choose the most suitable server block here, being compared with the specifiedserver_name
for the server block, and it will be exactly what you typed at the browser address bar (assuming IP address/domain name being typed will actually point to the nginx server). That means there is no sense to specify the same server name for different server blocks listening on the same TCP ports – the first one will always be chosen to process such a request, and the nginx will complain with thewarning message. For the developing purposes you can add the required domain names to the
hosts
system file, pointing them to your local machine, e.g.This way you will be able to use those domains from your local browser, the generated HTTP requests will contain the proper
Host
header and will be processed with your local nginx server instance.No. Looks like you don’t understand the internals of HTTP protocol. At the low level HTTP request will be something like
As you can see the host name and the request URL path are two completely different things. Usually this kind of tasks being solved using several location blocks:
However it will require support from the underlying web apps. Two available options are
Referring assets using relative URIs, e.g.
or
but not the using absolute URIs like
Using the same URI prefix as specified in the
location
directive, e.g.The reason should be obvious – every request for any first or second app assets should start with the
/app1/
or/app2/
prefix for being handled with the proper location block.As you can see, I’m using
/app1/
and/app2/
suffixes here rather than/app1
and/app2
. This is a very common mistake made by many people, to not understand the difference between those two. While it may seems to be an insignificant, in fact those two are drastically different in terms of browsing context which will be/
in first case and/app1/
or/app2/
in second case. Unless you are proxying some kind of API endpoint but a whole web application, you probably want the second one. To make it more easy, alocation
directive special behavior provided by nginx:Although we can override the browsing context using the
<base href="...">
HTML tag, I strongly recommend to not use this workaround and use a proper URI prefixes for your proxied web apps instead.