Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 922
Sam Avatar asked Nov 27 '22 13:11

Sam


1 Answers

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/

like image 198
Tarun Lalwani Avatar answered Apr 24 '23 05:04

Tarun Lalwani