Nginx container can't find plotly dash javascript within mounted volume - docker

I have a web service powered via plotly dash running in a docker container reverse proxied by an nginx container, all coordinated via docker compose.
docker-compose.yaml
services:
reverse_proxy:
image: nginx:1.17.10
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:Z,ro # nginx configuration
- ../../resources:/usr/share/nginx/html/:Z,ro # static assets, 404.html etc
- /etc/pki/tls/certs/:/etc/pki/tls/certs/:Z,ro # SSL stuff
ports:
- "80:80"
- "443:443"
depends_on:
- my_server
my_server:
image: my_server:v1.2.3
command: --config /app/configs/prod.yaml --port 8050 8051
nginx.conf
upstream my_server {
ip_hash;
server my_server:8050;
server my_server:8051;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl;
server_name my-server.com;
root /usr/share/nginx/html; # I assume this has something to do with it!
ssl_certificate /etc/pki/tls/certs/2022/my-server.crt;
ssl_certificate_key /etc/pki/tls/certs/2022/my-server.key;
ssl_password_file /etc/pki/tls/certs/2022/my-server.txt;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location /prod/app/ {
proxy_pass http://my_server/;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location = / {
root /usr/share/nginx/html; # or this...?
index index.html;
}
Upon running docker compose up --remove-orphans --force-recreate --renew-anon-volumes
I see the success message that my Dash server is running:
Dash is running on http://0.0.0.0:8050/
and the nginx container starts without error. However when I query my service via https://my-server.com/prod/app/
nginx fails to (cache?) and load plotly Dash javascript within its specified root directory:
# the location seems to be found and routed correctly
10.10.193.8 - - [28/Oct/2022:15:31:21 +0000] "GET /prod/app/ HTTP/1.1" 200 5324 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0" "-"
# fails due to css file not found
my-server-reverse_proxy-1 | 2022/10/28 15:31:21 [error] 7#7: *1 open() "/usr/share/nginx/html/assets/styles.css" failed (2: No such file or directory), client: 10.10.193.8, server: my-server.com, request: "GET /assets/styles.css?m=1666209805.0 HTTP/1.1", host: "my-server.com", referrer: "https://my-server.com/prod/app/"
# fails due to javascript not found
my-server-reverse_proxy-1 | 2022/10/28 15:31:21 [error] 7#7: *1 open() "/usr/share/nginx/html/_dash-component-suites/dash/dcc/dash_core_components.v2_6_2m1666209805.js" failed (2: No such file or directory), server: my-server.com, request: "GET /_dash-component-suites/dash/dcc/dash_core_components.v2_6_2m1666209805.js HTTP/1.1", host: "my-server.com", referrer: "https://my-server.com/prod/app/"
To debug I examined the contents of my nginx container the root directory does exist:
root#4c7190ea055a:/usr/share/nginx/html# ls
404.html 40x.html 50x.html bg.jpg index.html
I am not sure which of the following is causing this error:
nginx mis-configuration (I need to specify the server block root dir somewhere else?)
plotly Dash mis-configuration (I need to tell it to cache / load somewhere else?)
nginx docker volume issue (Doesnt seem to be the issue since I can view the folder inside the container?)
Any help is greatly appreciated!

Related

How can nginx be configured to forward different locations to different local ports?

I'm running nginx on docker and it is currently serving a webpage with SSL on let's say https://example.com
I've now created another set of containers that provide their own web server and it is available on port 8080 locally, and I want to be able to reach it in https://example.com/new_service
I've tried adding a simple proxy_pass of the /new_service/ location but I get a 502 Bad Gateway error and the nginx logs show the following:
2022/04/12 22:27:12 [error] 32#32: *19 connect() failed (111: Connection refused) while connecting to upstream, client:8.8.8.8, server: example.com, request: "GET /new_service HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
2022/04/12 22:27:12 [warn] 32#32: *19 upstream server temporarily disabled while connecting to upstream, client: 8.8.8.8, server: example.com, request: "GET /new_service/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
2022/04/12 22:27:12 [error] 32#32: *19 connect() failed (111: Connection refused) while connecting to upstream, client: 8.8.8.8, server: example.com, request: "GET /new_service/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
2022/04/12 22:27:12 [warn] 32#32: *19 upstream server temporarily disabled while connecting to upstream, client: 8.8.8.8, server: example.com, request: "GET /new_service/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
8.8.8.8 - - [12/Apr/2022:22:27:12 +0000] "GET /new_service/ HTTP/1.1" 502 157 "-" "My Browser" "-"
My current configuration is:
server {
listen 443;
server_name example.com;
ssl_certificate /etc/nginx/certs/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/example.com/privkey.pem;
root /var/www/html/;
client_max_body_size 1000M; # set max upload size
fastcgi_buffers 64 4K;
index index.php;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
add_header Strict-Transport-Security "max-age=15552000; includeSubdomains; ";
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ ^/(data|config|\.ht|db_structure\.xml|README) {
deny all;
}
location ~ /(conf|bin|inc)/ {
deny all;
}
location ~ /data/ {
internal;
}
location /new_service/ {
rewrite ^/new_service/?(.*) /$1 break;
proxy_pass http://localhost:8080/;
}
location / {
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;
try_files $uri $uri/ index.php;
}
location ~ ^(.+?\.php)(/.*)?$ {
try_files $1 = 404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$1;
fastcgi_param PATH_INFO $2;
fastcgi_param HTTPS on;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_pass php:9000;
# Or use unix-socket with 'fastcgi_pass unix:/var/run/php5-fpm.sock;'
#fastcgi_pass unix:/run/php/php7.3-fpm.sock;
}
location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
expires 30d;
# Optional: Don't log access to assets
access_log off;
}
}
I imagine it must be common practice to use nginx to direct several locations to different local containers, but I haven't been able to find good guidance on this. Any insight is greatly appreciated.
Please give docker config for a tailored answer.
With guessing: If your containers does not use host network but bridge network (which is default), localhost points to the localhost of the nginx container and not your host system.
# Using bridge network, if omitted will be same behavior
services:
service_name:
ports:
- "8080:8080" # Portmapping, maps from Container to HOST
networks:
network_name:
networks:
network_name:
With that setting nginx running on host or using network_mode: "host" can reach your service # localhost:8080. But if nginx is running in a container like described above, nginx CAN NOT REACH this service like that. Inter-container-communication is using an own (virtual) network with each container as "network adapter" in this network. Therefore with an own IP-Address. And for easy handling there is also a DNS-Server running, resolving the network aliases to IPs.
Therefore use proxy_pass http:\\DNS-NAME:8080\ or proxy_pass http:\\DOCKER-CONTAINER-IP:8080\ to reach the container inside docker network. Use docker inspect CONTAINER to determine this:
...
"NetworkSettings": {
"Networks": {
"NAME": {
"Aliases": [
"c4675dda79be" # <-- this
],
"IPAddress": "172.18.0.2", # <-- or that
}
Aliases are the DNS-Names and UID is used by default, further can be set by
docker run --net-alias
docker network connect --alias
# docker-compose:
services:
service_name: # <- this is used as an alias (=DNS-Name)
networks:
network_name:
aliases:
- alias1 # <- additional alias
As long as it is possible use this network segregation (by default) and not "host-mode" for your containers due to strange side effects and security reasons and so on. Therefore you do not need port-mapping for your services hidden behind nginx at all. Because it does not need to be published on host (maybe except debugging and development), so our service is more secured, because nginx just forwards stuff to your service you allowed and not everything accessing your host on a given port.
It sounds like to me that the new docker container isn't allowing you through it's firewall or you haven't passed the ports through to the host

Why does my static Docker give 502 errors?

I am trying to create a docker deployable django site with a seperate static Nginx server. This used to work fine, but suddenly stopped working. I now keep getting 502 errors when trying to access the static folder. The Django app is running on a gunicorn server.
This is my nginx.conf
# nginx.default
upstream staticserver {
ip_hash;
server staticserver:9010;
}
server {
location / {
proxy_pass http://127.0.0.1:8010;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
proxy_pass http://staticserver;
}
listen 9000;
server_name localhost;
}
My docker compose is this
version: '3'
services:
staticserver:
build:
context: .
dockerfile: ./staticserver/Dockerfile
ports:
- "9010:80"
djangoserver:
build:
context: .
dockerfile: Dockerfile
ports:
- "9000:9000"
depends_on:
- staticserver
If I go to 127.0.0.1:9000 I get the django site
If I go to 127.0.0.1:9010 I get the root of the static server
But, if I go to 127.0.0.1/static I get a 502 error.
The logs show entries like these
[error] 10#10: *25 connect() failed (111: Connection refused) while connecting to upstream, client: 172.21.0.1, server: localhost, request: "GET /static HTTP/1.1", upstream: "http://172.21.0.2:9010/static", host: "127.0.0.1:9000"
This seems counterintuitive, as I'd expect it to be http://172.21.0.2:9010/ with the static folder names stripped.
I've tried some of the other answers on relating topics, but so far, it seems it just stopped working. I suspect some issue in the config files that I am simply not aware of, but I can't seem to find my mistake.
Referring to a port on the inner network solved the issue;
upstream staticserver {
ip_hash;
server staticserver;
}
instead of
upstream staticserver {
ip_hash;
server staticserver:9010;
}

How to use NGINX to forward the request to Docker Microservice

I wanted to use NGINX as a reverse proxy to forward the request to microservices.
Both NGINX and Microservices are hosted on docker container.
Below is my nginx.conf file
worker_processes 1;
events { worker_connections 1024; }
#test
http {
sendfile on;
# upstream docker-nginx {
# server nginx:80;
# }
upstream admin-portal {
# server admin-portal:9006;
server xx.xx.xx.xx:9006;
# server localhost:9006;
}
server {
listen 8080;
location / {
proxy_pass http://admin-portal;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
Dockerfile
FROM nginx
RUN apt-get update && apt-get install -y \
curl
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 8080
docker-compose.yml
version: '3'
services:
nginx:
restart: always
build: ../../conf/
volumes:
- ./mysite.template:/etc/nginx/conf.d/mysite.template
ports:
- "8080:8080"
networks:
- cloud
networks:
cloud:
driver: bridge
I am able to access nginx home page by localhost:8080
admin-portal is a microservice running on 9006 port
But if I do localhost:8080/admin-portal/ I am getting below error
nginx_1 | 2018/07/04 07:08:17 [error] 7#7: *1 "/usr/share/nginx/html/admin-portal/index.html" is not found (2: No such file or directory), client: xx.xx.xx.xx, server: your-domain.com, request: "GET /admin-portal/ HTTP/1.1", host: "xx.xx.xx.xx:8080"
nginx_1 | 2018/07/04 07:08:17 [error] 7#7: *1 open() "/usr/share/nginx/html/404.html" failed (2: No such file or directory), client: xx.xx.xx.xx, server: your-domain.com, request: "GET /admin-portal/ HTTP/1.1", host: "xx.xx.xx.xx:8080"
nginx_1 | xx.xx.xx.xx - - [04/Jul/2018:07:08:17 +0000] "GET /admin-portal/ HTTP/1.1" 404 170 "-" "curl/7.47.0"
admin-portal/
Please suggest what changes I need to do to forward the request to admin-portal using nginx
upstream admin-portal {
server 127.0.0.1:9006;
}
it should be :
upstream admin-portal {
server 172.17.0.1:9006;
}
With 172.17.0.1 is ip address gateway of containers.
Or docker inspect containermicroservice_id then get ip address of that container.
upstream admin-portal {
server ipaddressofmicroservicecontainer:9006;
}
Put ip address of server into
server_name localhost ipaddressofserver www.example.com;
then access http://ipaddressofserver:8080/admin-portal
Comment out this part:
#server {
# listen 8080;
# server_name your-domain.com www.your-domain.com;
# root /usr/share/nginx/html;
# index index.html index.htm;
# error_page 404 /404.html;
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# root html;
# }
}

Dockerized Nginx redirect different subdomains to the same page

Background
I am trying to set up a home server with a bunch of webapps. For now, I am focusing on seafile and a static html page. The server uses Docker and Nginx.
I want to achieve the following behavior:
The address domain-name.eu redirects to the static pages, saying "Welcome to Domain Name".
The address seafile.domain-name.eu redirects to the seafile container.
Problem description
I followed various tutorials on the web on how to set up a docker-compose.yml and the nginx conf to allow nginx to serve different website. I manage to have my seafile working alone behind nginx on the right address, and I manage to have the static page working alone behind nginx on the right address. When I try to mix both, both domain-name.eu and seafile.domain-name.eu serve the static page "Welcome to Domain Name".
Here is my docker-compose.yml:
nginx:
image: nginx
ports:
- 80:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./html/:/usr/share/nginx/html
links:
- seafile
seafile:
image: seafileltd/seafile:latest
expose:
- 80
volumes:
- /home/docker/seafile-data:/shared
And my nginx.conf:
http {
upstream seafile {
server seafile;
}
server {
listen 80;
server_name seafile.domain-name.eu;
location /{
proxy_pass http://seafile/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 80;
server_name domain-name.eu;
root /usr/share/nginx/html;
index index.html index.htm;
}
}
events {}
When I try to access seafile.domain-name.eu, I receive this log from the nginx container:
nginx_1 | xxx.xxx.xxx.xxx - - [05/Jun/2018:09:44:24 +0000] "GET / HTTP/1.1" 200 22 "http://seafile.domain-name.eu/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0"
And when I try to access domain-name.eu, I receive this:
nginx_1 | xxx.xxx.xxx.xxx - - [05/Jun/2018:10:07:11 +0000] "GET / HTTP/1.1" 200 22 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0"
So the address is indeed recognized for the seafile, which helped me eliminating a bad configuration of my DNS as a possible cause. Or am I mistaken?
Can anyone help me troubleshooting the problem? 
Thanks.
EDIT: Adding docker ps output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b6d018169d76 nginx "nginx -g 'daemon of…" About an hour ago Up About an hour 0.0.0.0:80->80/tcp jarvis-compose_nginx_1
7e701ce7650d seafileltd/seafile:latest "/sbin/my_init -- /s…" About an hour ago Up About an hour 80/tcp jarvis-compose_seafile_1
EDIT 2 : the problem was due to a configuration error (see accepted answer) + a residual redirection from my old registrar that was causing weird behavior. Thanks for the help! 
Have trying this to run on my local. Found that you've mount wrong nginx config file in the container. nginx.conf should mounted on /etc/nginx/conf.d/default.conf, it's the default config to supporting vhost on nginx. Below are the correct setups:
nginx.conf
upstream seafile {
server seafile;
}
server {
listen 80;
server_name seafile.domain-name.eu;
location /{
proxy_pass http://seafile/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 80;
server_name domain-name.eu;
root /usr/share/nginx/html;
index index.html index.htm;
}
docker-compose.yml
version: '3'
services:
nginx:
image: nginx
ports:
- 80:80
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./html/:/usr/share/nginx/html
links:
- seafile
container_name: web
seafile:
image: seafileltd/seafile:latest
expose:
- 80
volumes:
- /home/docker/seafile-data:/shared
container_name: seafile_server

Docker nginx reverse proxy gives "502 Bad Gateway"

I'm trying to have a docker container with nginx work as reverse proxy to other docker containers and I keep getting "Bad Gateway" on locations other other than the base location '/'.
I have the following server block:
server {
listen 80;
location / {
proxy_pass "http://game2048:8080";
}
location /game {
proxy_pass "http://game:9999";
}
}
It works for http://localhost but not for http://localhost/game which gives "Bad Gateway" in the browser and this on the nginx container:
[error] 7#7: *6 connect() failed (111: Connection refused)
while connecting to upstream, client: 172.17.0.1, server: ,
request: "GET /game HTTP/1.1", upstream: "http://172.17.0.4:9999/game",
host: "localhost"
I use the official nginx docker image and put my own configuration on it. You can test it and see all details here:
https://github.com/jollege/ngprox1
Any ideas what goes wrong?
NB: I have set local hostname entries on docker host to match those names:
127.0.1.1 game2048
127.0.1.1 game
I fixed it! I set the server name in different server blocks in nginx config. Remember to use docker port, not host port.
server {
listen 80;
server_name game2048;
location / {
proxy_pass "http://game2048:8080";
}
}
server {
listen 80;
server_name game;
location / {
# Remember to refer to docker port, not host port
# which is 9999 in this case:
proxy_pass "http://game:8080";
}
}
The github repo has been updated to reflect the fix, the old readme file is there under ./README.old01.md.
Typical that I find the answer when I carefully phrase the question to others. Do you know that feeling?
I had the same "502 Bad Gateway" error, but the solution was to tune proxy_buffer_size following this post instructions:
proxy_buffering off;
proxy_buffer_size 16k;
proxy_busy_buffers_size 24k;
proxy_buffers 64 4k;
See the nginx error log
sudo tail -n 100 /var/log/nginx/error.log
If you see Permission denied error in the log like below -
2022/03/28 03:51:09 [crit] 1140954#0: *141 connect() to
xxx.xxx.68.xx:8080 failed (13: Permission denied) while connecting to
upstream, client: xxx.xx.xxx.25, server: www.example.com
See whether the value of httpd_can_network_connect is enabled or not by running the command: sudo getsebool -a | grep httpd
If you see the value of httpd_can_network_connect is off then this is the cause of your issue.
Solution:
set the value of httpd_can_network_connect is on by run the command sudo setsebool httpd_can_network_connect on -P
Hope it will resolve your problem.
I had the same error, but for a web application that was just not serving at the IP and port mentioned in the config.
So say you have this:
location /game {
proxy_pass "http://game:9999";
}
Then make sure the web application that you expect at http://game:9999 is really serving from within a docker container named 'game' and the code is set to serve the app at port 9999.
For me helped this line of code proxy_set_header Host $http_host;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_pass http://myserver;
}
In my case, after 4 hours, only I missed put the port with semanage command.
location / {
proxy_pass http://A.B.C.D:8090/test;
}
The solution was add 8090 port and works.
semanage port -a -t http_port_t -p tcp 8090
You have to declare an external network if the container you are pointing to is defined in another docker-compose.yml file:
version: "3"
services:
webserver:
image: nginx:1.17.4-alpine
container_name: ${PROJECT_NAME}-webserver
depends_on:
- drupal
restart: unless-stopped
ports:
- 80:80
volumes:
- ./docroot:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
networks:
- internal
- my-passwords
networks:
my-passwords:
external: true
name: my-passwords_default
nginx.conf:
server {
listen 80;
server_name test2.com www.test2.com;
location / {
proxy_pass http://my-passwords:3000/;
}
}
You may need to telnet on the upstream machine to check to wither it's connected:
tracing the /var/log/nginx/error.log would help.

Resources