Supergator
Supergator

Reputation: 51

Set up Nginx with Docker and gunicorn - error 111: Connection refused

I am trying to set up docker + gunicorn + angular + nginx environment:

All /api/* requests should be handled by gunicorn, however, for some reason, nginx refuses the connection with error 111.

Nginx cannot connect with gunicorn, see below docker logs:

docker-compose -f docker-compose-prod.yml up --build
...
api_1 | [2022-03-18 18:02:46 +0000] [1] [INFO] Starting gunicorn 20.0.4
api_1 | [2022-03-18 18:02:46 +0000] [1] [DEBUG] Arbiter booted
api_1 | [2022-03-18 18:02:46 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
api_1 | [2022-03-18 18:02:46 +0000] [1] [INFO] Using worker: sync
api_1 | [2022-03-18 18:02:46 +0000] [9] [INFO] Booting worker with pid: 9
api_1 | [2022-03-18 18:02:46 +0000] [1] [DEBUG] 1 workers
client_1 | 192.168.32.1 - - [18/Mar/2022:18:03:20 +0000] "GET /api/checkmongo HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36" "-"
client_1 | 2022/03/18 18:03:20 [error] 23#23: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.32.1, server: api, request: "GET /api/checkmongo HTTP/1.1", upstream: "http://173.37.145.221:5000/api/checkmongo", host: "localhost:4200"

docker-compose-prod.yml

version: '3.7'

services:

   client:
      build:
         context: ./frontend
         dockerfile: Dockerfile-prod
      volumes:
         - ./frontend:/app
         - ./frontend/src:/app/src # for watching files
      ports:
         - "4200:80"
      networks:
         - frontend

   mongodb:
      image: mongo
      container_name: mongo
      restart: unless-stopped
      command: mongod --auth
      environment:
         MONGO_INITDB_ROOT_USERNAME: "admin"
         MONGO_INITDB_ROOT_PASSWORD: "password"
         MONGO_INITDB_DATABASE: webapp
         MONGODB_DATA_DIR: /data/db
      volumes:
         - mongodbdata:/data/db
      networks:
         - backend

   api:
      build:
         context: ./backend
         dockerfile: Dockerfile
      command: gunicorn --log-level=debug --bind 0.0.0.0:5000 main:app
      ports:
         - "5000:5000"
      environment:
         MONGODB_HOST: mongodb
         MONGODB_USERNAME: "admin"
         MONGODB_PASSWORD: "password"
      volumes:
         - appdata:/var/www/
      depends_on:
         - mongodb
      networks:
         - frontend
         - backend

networks:
   frontend:
      driver: bridge
   backend:
      driver: bridge
volumes:
   mongodbdata:
      driver: local
   appdata:
      driver: local

frontend/Dockerfile-prod

#stage 1
FROM node:17.6.0 as node
WORKDIR /app
COPY . /app
RUN npm install
RUN npm run build --prod

#stage 2
FROM nginx:alpine
COPY --from=node /app/dist/automation /usr/share/nginx/html

RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

frontend/nginx.conf

upstream web-app_api {
    server api:5000;
}

server {
    listen 80;
    server_name api;

    location /api {
        proxy_pass http://web-app_api;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_redirect off;
    }

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

}

backend/Dockerfile

# Create our image based on Python 3.8
FROM python:3.8

# Expose ports
EXPOSE 5000

# Tell Python to not generate .pyc
ENV PYTHONDONTWRITEBYTECODE 1

# Turn off buffering
ENV PYTHONUNBUFFERED 1

# Install requirements using pip
ADD req .
RUN python -m pip install -r req

# Set working directory and add our Flask API files
WORKDIR /app
ADD . /app

I have been struggling with this error for many hours - trying to change nginx, gunicorn conf - without success.

EDIT: Once, I have removed following lines from docker-compose-prod.yml, the error is gone (I don't know why):

     depends_on:
        - mongodb

Upvotes: 1

Views: 870

Answers (1)

Hans Kilian
Hans Kilian

Reputation: 25597

It sounds like (at least part of) your problem is that Nginx doesn't strip /api/ from the requests before passing them on. To achieve that, you add a / at the end of the location so it becomes /api/ rather that /api like this

upstream web-app_api {
    server api:5000;
}

server {
    listen 80;
    server_name api;

    location /api/ {
        proxy_pass http://web-app_api;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_redirect off;
    }

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

}

Upvotes: 0

Related Questions