502 Bad Gateway when using reverse proxy with Docker and Nginx - docker

I have searched StackOverflow for my problem but I always seem to be hitting the 502 Bad Gateway with my Nginx Docker configuration. I am trying to access pgadmin4 using my domain mydomain.com/pgadmin instead of mydomain.com:8060 where 8060 is the port exposed by it's docker container. My docker-compose.yml file looks like this:
version: '3.5'
services:
reverse-proxy:
image: nginx:1.19.6
restart: always
ports:
- "80:80"
- "443:443"
postgres:
image: postgres:12
ports:
- "5432:5432"
pgadmin:
image: dpage/pgadmin4
depends_on:
- postgres
ports:
- "8060:80"
networks:
default:
external:
name: defaultnetwork
The default.conf file of my nginx container looks like this:
upstream pgadmin {
server 127.0.0.1:8060;
}
server {
listen 80;
listen [::]:80;
server_name mydomain.com;
root /usr/share/nginx/html;
index index.html index.htm;
location /pgadmin {
proxy_pass http://pgadmin;
}
}
With this configuration, I keep getting the 502 Bad Gateway error. Could someone kindly point to me where I am going wrong. I would really appreciate it.
Thanks.
[EDIT]
This is from the docker logs:
2021/02/03 08:07:42 [error] 23#23: *2 connect() failed (111: Connection refused) while connecting to upstream, client: ***.***.***.***, server: mydomain.com, request: "GET /pgadmin HTTP/1.1", upstream: "http://127.0.0.1:8082/pgadmin", host: "mydomain.com"

The 502 problem comes from the loopback IP here:
upstream pgadmin {
server 127.0.0.1:8060;
}
127.0.0.1 or localhost for the NGINX container is the NGINX container itself. You should use the name of the service instead:
upstream pgadmin {
server pgadmin:8060;
}
Name of the service comes from the docker-compose.yml:
services:
pgadmin: # <- this
image: dpage/pgadmin4
If you hit 404 after these changes, this is because you have to change base path of the application. Try using this config:
location /pgadmin/ {
proxy_set_header X-Script-Name /pgadmin;
proxy_set_header Host $host;
proxy_pass http://pgadmin;
proxy_redirect off;
}

Since your containers are working in the same network, you should access the Pgadmin container via 80th port from your Nginx container.
You should replace this line server 127.0.0.1:8060 with server pgadmin:80 in your Nginx config.

Related

docker nginx proxy to linked container not working

I have tried this:
NGINX reverse proxy not working to other docker container
and this:
Docker nginx-proxy : proxy between containers
and followed nginx config from here:
nginx proxy_pass to a linked docker container
I am simply trying to tell nginx to proxy to a linked api service on port 4000. I do not want to expose 4000 to host machine because there will be multiple services running on this port.
This is my docker-compose.yml:
version: '3'
services:
api:
build: ./api
image: myapi:latest
container_nameE: api
api_nginx:
image: nginx:latest
container_name: api_nginx
depends_on:
- api
links:
- api
ports:
- "80:80"
environment:
- NGINX_SERVER_NAME:localhost
volumes:
- ./nginx:/etc/nginx/conf.d
...
...
and my nginx server is super minimal:
upstream backend {
server api;
}
server {
listen 80;
listen [::]:80;
server_name ${NGINX_SERVEE_NAME};
location / {
resolver 127.0.0.1;
proxy_pass http://backend/$1;
}
}
This is the error is throwing:
...[error] 20#20: *1 no resolver defined to resolve api, client: 172.23.0.1, server: ${nginx_server_name}....
and the page shows a 502 Bad Gateway
What is going on? I've followed other people's nginx configs and it's not working, I have no idea.

Nginx Proxy Upstream Server Docker Compose - 502 Bad Gateway Connection Refused

I am trying to containerize all things related to my web app using Docker Compose, including Nginx & SSL Certificates. To do this I am using the Nginx Proxy image from JWilder and the LetsEncrypt Companion, but am having trouble getting the nginx proxy to work, result ends up being:
Nginx 502 Bad Gateway
[error] 31160#0: *35 connect() failed (111: Connection refused) while connecting to upstream, client: xx.xx.xx.xx, server: domain.com, request: "GET /dev/ HTTP/1.1", upstream: "webapp://127.0.0.1:8080", host: "domain.com"
This only happened when trying to set up the Nginx proxy and SSL certificates so I know it's a configuration issue for either or both of these containers. If anyone can spot where I am going wrong, I would be extremely grateful!
Here are the containers in question:
version: '3.1'
networks:
mywebapp:
services:
nginx-proxy:
container_name: nginx-proxy
build: ./env/nginx-proxy
networks:
- mywebapp
ports:
- 80:80
- 443:443
env_file:
- ./env/nginx-proxy/.env
depends_on:
- webapp
tty: true
volumes:
- ./src:/home/www/mywebapp/src
- ./storage:/home/www/storage/mywebapp
- ./data/nginx-proxy/logs:/var/log/nginx
- ./env/nginx-proxy/webserver/nginx.conf:/etc/nginx/nginx.conf
- ./env/nginx-proxy/webserver/conf.d:/etc/nginx/conf.d
- ./env/nginx-proxy/webserver/vhost.d:/etc/nginx/vhost.d
- ./env/nginx-proxy/webserver/defaults:/etc/nginx/defaults
- ./env/nginx-proxy/webserver/global:/etc/nginx/global
- ./env/nginx-proxy/ssl/certs:/etc/nginx/certs
- ./env/nginx-proxy/share:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
labels:
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
letsencrypt:
restart: always
container_name: letsencrypt
image: jrcs/letsencrypt-nginx-proxy-companion
env_file:
- ./env/letsencrypt/.env
volumes:
- ./data/letsencrypt/logs:/var/log
- ./env/nginx-proxy/webserver/nginx.conf:/etc/nginx/nginx.conf
- ./env/nginx-proxy/webserver/conf.d:/etc/nginx/conf.d
- ./env/nginx-proxy/webserver/vhost.d:/etc/nginx/vhost.d
- ./env/nginx-proxy/webserver/defaults:/etc/nginx/defaults
- ./env/nginx-proxy/webserver/global:/etc/nginx/global
- ./env/nginx-proxy/ssl/certs:/etc/nginx/certs
- ./env/nginx-proxy/share:/usr/share/nginx/html
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- nginx-proxy
webapp:
container_name: webapp
build: ./env/webapp
hostname: webapp
networks:
- mywebapp
ports:
- 9000:9000
- 8080:8080
volumes:
- ./env/composer:/home/www/.composer
- ./env/global/bashrc:/home/www/.bashrc
- ./data/bash/.bash_history:/home/www/.bash_history
- ~/.ssh:/home/www/.ssh:ro
- ~/.gitconfig:/home/www/.gitconfig:ro
- ./storage:/home/www/storage/mywebapp
- ./src:/home/www/mywebapp/src
Key points being:
Webapp is the source of my web application which is running PHP, MySQL and Nginx webserver. The webapp webserver exposes and listens on port 8080 to serve the PHP files.
Nginx proxy exposes standard ports 443 and 80 and proxy passes to webapp on port 8080
LetsEncrypt Companion generates the certs and renews.
Nginx Proxy server configuration:
upstream webapp {
server 127.0.0.1:8080;
}
server {
listen 80;
listen [::]:80;
server_name webapp.localhost;
location / {
proxy_pass http://webapp;
}
}
server {
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate certs/default.crt;
ssl_certificate_key certs/default.key;
include /etc/nginx/global/ssl-params.conf;
server_name webapp.localhost;
location / {
proxy_pass http://webapp;
}
}
Webapp webserver configuration:
server {
listen 8080;
listen [::]:8080;
server_name webapp.localhost;
root /home/www/webapp/src;
index index.php;
include /etc/nginx/defaults/php.conf;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
}
When visiting http://webapp.localhost:8080 I can see the webapp webserver serves the page no trouble, so I suspect it's something wrong with my Nginx Proxy server configuration.
Thanks for reading.
Since nginx and webapp are on two separate containers, nginx can't reach webapp on localhost(127.0.0.1) as you've configured for upstream:
upstream webapp {
server 127.0.0.1:8080;
}
Change it to webapp:8080.

DNS in docker-compose, map to non-80 port?

While experimenting with docker-compose, I'm running into some issues with NGINX and the dns. The error is the regular "connection refused while connecting to upstream" in NGINX. I think the problem arises due to the port numbers.
Examples online like this one run the NGINX on port 80, which doesn't cause the issue.
The docker-compose.yml:
version: '3'
services:
http-server:
networks:
- mynetwork
image: nginx_image
ports:
- 8080:8080
depends_on:
- frontend
- rest_api
frontend:
networks:
- mynetwork
image: frontend_image
ports:
- 8001:8001
rest_api:
networks:
- mynetwork
image: rest_api_image
ports:
- 8000:8000
networks:
mynetwork:
driver: bridge
nginx.conf for nginx_image has this block:
server {
listen 8080;
location /static/js/ {
proxy_pass http://frontend;
}
location /static/css/ {
proxy_pass http://frontend;
}
location /static/ {
proxy_pass http://rest_api;
}
location / {
proxy_pass http://frontend;
}
location /rest_api/ {
proxy_pass http://rest_api;
}
}
Now, both the frontend and api are called over port 80, while it should be 8001 and 8000.
What am I missing? I would expect docker-compose to make the port mapping automatically.
Thanks in advance!
Kind regards,
DA
EDIT1: here's the error (including the hostname suggestion)
EDIT2: updated the question
http-server_1 | 2018/06/04 14:47:50 [error] 14#14: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: , request: "GET /rest_api/admin/ HTTP/1.1", upstream: "http://172.18.0.2:80/rest_api/admin/", host: "localhost:8080"
you have to specify hostnames:
frontend:
image: frontend_image
hostname: frontend
ports:
- 8001:8001
rest_api:
hostname: rest_api

How to connect from nginx on docker host to application in container

The situation is: we have service with nginx, which also acts as docker server.
Also we have Java application in docker container, which listens at 8080.
The problem is permissions to connect from nginx to container's published port.
Nginx.error.log shows:
2017/11/23 13:44:12 [crit] 3599#0: *1 connect() to 127.0.0.1:8080 failed (13: Permission denied) while connecting to upstream,
2017/11/23 13:44:13 [error] 3599#0: *1 no live upstreams while connecting to upstream
Site config is:
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass http://localhost:8080;
include proxy.conf;
}
}
Container config:
version: '3'
services:
app:
image: user/appX
restart: always
container_name: appX
ports:
- "8080:8080"
env_file:
- ./appX.env
extra_hosts:
- "host:172.101.0.1"
networks:
mynet:
ipv4_address: 172.101.0.2
networks:
mynet:
external:
name: mynet
Permission happens because nginx user is nginx and docker user is root.
How to fix this problem without moving nginx to container ?
Or maybe there is some work around exists ?
Problem was in SELinux configuration.
Solved by running:
setsebool -P httpd_can_network_connect 1

Connection refused while connecting to upstream when using nginx as reverse proxy

The setup is as follows: I have a Gunicorn/Django app running on 0.0.0.0:8000 that is accessible via the browser. To serve static files I am running nginx as a reverse proxy. /etc/nginx/nginx.conf is configured to forward requests as follows:
server {
location /static/ {
alias /data/www/;
}
# Proxying the connections
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://0.0.0.0:8000;
}
}
and my docker-compose.yml file is as follows:
version: '3.3'
services:
web:
restart: always
build: ./web
expose:
- "8000"
ports:
- "8000:8000"
volumes:
- staticdata:/usr/src/app/static_files
command: gunicorn wsgi:application --workers 2 --bind 0.0.0.0:8000
depends_on:
- postgres
nginx:
restart: always
build: ./nginx
ports:
- "80:80"
- "443:443"
volumes:
- staticdata:/data/www
depends_on:
- web
postgres:
image: postgres:9.2
restart: always
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
staticdata:
pgdata:
When I visit 0.0.0.0:8000 via the browser the application works fine (albeit without serving static files), but when I visit 127.0.0.1:80 I get the following error:
nginx_1 | 2017/09/17 13:59:46 [error] 6#6: *5 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://0.0.0.0:8000/", host: "127.0.0.1"
I know that this error indicates that the server running on 0.0.0.0:8000 is not accepting requests, but since I can visit it via the browser I am a bit confused.
Thank you in advance.
Change your proxy_pass from
proxy_pass http://0.0.0.0:8000;
to
proxy_pass http://web:8000;
Your nginx needs to forward to request the web container
Edit-1: Explanation
0.0.0.0 is a special IP address which is used to refer to any available interface on the machine. So if your machine has a loopback (lo), ethernet (eth0), Wifi (wlan0) with respective IP as 127.0.0.1, 192.168.0.100, 10.0.0.100.
So now while listening for incoming connection you can choose any of the above IP
gunicorn wsgi:application --workers 2 --bind 10.0.0.100:8000
This will only be reachable from your Wifi network. But other machines on Lan network can't visit it. So if you want your app to listen on any available network on the machine you use a special IP 0.0.0.0. This means bind on all network interfaces
gunicorn wsgi:application --workers 2 --bind 0.0.0.0:8000
Now when you access the app using http://0.0.0.0 it is equivalent to using 127.0.0.1. So your proxy_pass http://0.0.0.0:8000; is equivalent to proxy_pass http://127.0.0.1:8000;
So when you run that in nginx container, it passes on the request on port 8000 of the same container and there is nothing running on 8000 in your nginx container. So you need to send that request to the your gunicorn container. This is reachable using the service name web in docker-compose.
See the below article for more details https://docs.docker.com/compose/networking/

Resources