How to use NGINX to forward the request to Docker Microservice - docker

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;
# }
}

Related

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

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!

Docker - Nginx proxy_pass "502 bad gateway" only with client routes?

I have the following docker compose:
version: '3.1'
services:
backend:
container_name: backend
image: backendnode
restart: always
ports:
- 3000:3000
frontend:
container_name: frontend
image: frontnginx
restart: always
ports:
- 4200:80
apigw:
image: reverseproxy
restart: always
ports:
- 80:80
depends_on:
- frontend
- backend
This is the reverseproxy image nginx.conf:
worker_processes auto;
events { worker_connections 1024; }
http {
server {
listen 80;
server_name localhost 127.0.0.1;
location / {
proxy_pass http://frontend:4200;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /api {
proxy_pass http://backend:3000;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}
When running docker-compose run, I get the following results:
localhost:80/api/users: works great, nginx redirects to backend properly.
localhost:80/index.html: not working, I get the following error:
connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: localhost, request: "GET /index.html HTTP/1.1", upstream: "http://172.20.0.5:4200/index.html", host: "localhost:80"
Frontend is a simple nginx web server, this is its nginx.conf:
events{}
http {
include /etc/nginx/mime.types;
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
}
Any idea why reverse proxy it's not working with frontend routes?
Created answer from the comment thread:
Docker networking works like this: if you use communication within docker's network, you need to refer to the internal ports. Since port mapping is used for the "outside world". So in your case, you would need to refer to "frontend:80" instead of 4200.

NGINX multiple server blocks - 502 Bad Gateway

I'm trying to setup multiple servers using Nginx and Docker. For now, I want to make it work locally but I'll export this into to use it in a website. My nginx.conf is:
worker_processes 1;
events { worker_connections 1024; }
http {
client_max_body_size 2048M;
sendfile on;
upstream docker-phpmyadmin {
server phpmyadmin;
}
upstream docker-wordpress {
server wordpress;
}
upstream docker-api {
server api;
}
upstream docker-frontend {
server frontend;
}
server {
listen 80;
server_name example.com;
location / {
proxy_set_header Host $http_host;
proxy_pass http://docker-frontend;
}
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_set_header Host $http_host;
proxy_pass http://docker-api;
}
}
server {
listen 80;
server_name db.example.com;
location / {
proxy_set_header Host $http_host;
proxy_pass http://docker-phpmyadmin;
}
}
server {
listen 80;
server_name admin.example.com;
location / {
proxy_read_timeout 3600;
proxy_set_header Host $http_host;
proxy_pass http://docker-wordpress;
}
}
}
I've added these entries to my /etc/hosts:
127.0.0.1 example.com
127.0.0.1 db.example.com
127.0.0.1 api.example.com
127.0.0.1 admin.example.com
My docker-compose.yml contains:
nginx:
build: ./backend/nginx
links:
- wordpress
- phpmyadmin
- frontend
ports:
- ${NGINX_EXTERNAL_PORT}:80
volumes:
- "./backend/nginx/nginx.conf:/etc/nginx/nginx.conf"
So, locally, NGINX_EXTERNAL_PORT is set to 5000. I can access to db.example.com:5000 and to admin.example.com:5000, but when I try to access to my main page example.com:5000 I get:
nginx_1 | 2019/09/18 21:26:52 [error] 6#6: *8 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: example.com, request: "GET / HTTP/1.1", upstream: "http://172.18.0.7:80/", host: "example.com:5000"
nginx_1 | 172.18.0.1 - - [18/Sep/2019:21:26:52 +0000] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36"
Am I missing something on my configuration for that server block? Thanks!
It turned out to be because the application that was in example.com was not exposing any port, so after including EXPOSE 3000 to the Dockerfile and changing the upstream to
upstream docker-frontend{
server frontend:3000;
}
Works!

Local subdomains using Nginx and Docker Compose

I want to test different subdomains locally, using nginx and docker-compose.
docker-compose.yml:
version: '2'
services:
...
phpmyadmin:
depends_on:
- db
image: phpmyadmin/phpmyadmin
restart: unless-stopped
ports:
- 8081:80
environment:
PMA_HOST: db
MYSQL_ROOT_PASSWORD: p4ssw0rd!
...
nginx:
build: ./backend/nginx
links:
- phpmyadmin
ports:
- "4000:80"
volumes:
- "./backend/nginx/nginx.conf:/etc/nginx/nginx.conf"
nginx.conf:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream docker-phpmyadmin {
server phpmyadmin:8081;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://docker-phpmyadmin;
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;
}
}
}
Nginx Dockerfile:
FROM nginx:alpine
COPY ./nginx.conf /etc/nginx/nginx.conf
etc/hosts:
127.0.0.1 example.com
127.0.0.1 api.example.com
127.0.0.1 admin.example.com
When I run my nginx container and I navigate to api.example.com:4000 on my browser I see a 502 Bad Gateway page, and inside the container I get this message:
nginx_1 | 2019/07/27 12:17:00 [error] 6#6: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.21.0.1, server: api.example.com, request: "GET / HTTP/1.1", upstream: "http://172.21.0.4:8081/", host: "api.example.com:4000"
I guess that it should work using the port 80 instead of the 4000 but how can I test my configuration locally?
Thanks
I was able to fix it by changing my upstream server port to 80:
upstream docker-phpmyadmin {
server phpmyadmin;
}

Using Nginx reverse proxy with Docker

I am trying to develop a distributed Angular app deployed on Nginx that should connect to a backend service.
docker-compose.yml:
version: '3'
services:
backend_service_1:
build:
context: ./app
dockerfile: Dockerfile
ports:
- "3001:5000"
networks:
- my-network
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.3
ports:
- "3000:80"
networks:
- my-network
links:
- backend_service_1
networks:
my-network:
nginx.conf:
upstream backend {
server backend_service_1:3001;
}
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html/ki-poc;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
location /backend {
proxy_pass http://backend/;
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;
}
}
I can access the app on localhost:3000. I can also get a response from the backend service on localhost:3001 using the browser. However, when I try to get a response from the backend service using the proxy on localhost:3000/backend I receive the following error message:
[error] 5#5: *4 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: localhost, request: "GET /backend HTTP/1.1", upstream: "http://172.20.0.2:3001/", host: "localhost:3000"
Can you tell my, why the request to the linked backend container is getting refused?
You shoul use the port of the container in the nignx config, not the one of the host.
upstream backend {
server backend_service_1:5000;
}

Resources