imhans4305
imhans4305

Reputation: 697

Running FastAPI in docker with uvicorn and gunicorn nginx

I am trying to build a FastAPI application with ubuntu 22.04 docker image, gunicorn and uvicorn and nginx as webserver. Gunicorn and uvicorn services are started using supervisord.

python is installed in a virtual environment located in /opt/venv

Dockerfile

FROM ubuntu:22.04
LABEL maintainer="test"
ENV GROUP_ID=1000 \
    USER_ID=1000
RUN apt-get update && apt-get install -y apt-transport-https ca-certificates supervisor procps cron python3.10-venv python3-gdbm wget gnupg unzip curl
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN ["python", "-m", "pip", "install", "--upgrade", "pip", "wheel"]
RUN apt-get install -y  python3-wheel
COPY ./requirements.txt /app/requirements.txt
RUN ["python", "-m", "pip", "install", "--no-cache-dir", "--upgrade", "-r", "/app/requirements.txt"]
COPY ./app /app
RUN which python

nginx is using a separate docker image. Mongodb is the database and the content of docker-compose is

docker-compose.yml

version: '3.10'
services:
  web:
    container_name: "fastapi"
    build: ./
    volumes:
      - ./app:/app
    ports:
      - "8000:8000"
    environment:
      - DEPLOYMENT_TYPE=production
    depends_on:
      - mongo
    links:
      - mongo

  nginx:
    container_name: "nginx"
    restart: always
    image: nginx
    volumes:
      - ./app/nginx/conf.d:/etc/nginx/conf.d
    ports:
      - 80:80
      - 443:443
    links:
      - web

python packages are specified in requirements.txt

requirements.txt

setuptools>=59.1.1,<59.7.0 
fastapi==0.87.0 
uvicorn==0.19.0 
gunicorn==20.1.0
python-decouple==3.5

nginx configuration file is

app.conf

upstream web {
    server web:8000;
}

server {

    listen 80;
    charset utf-8;
    server_name 0.0.0.0;
    client_max_body_size 20m;
    proxy_read_timeout 300;
    proxy_connect_timeout 300;
    proxy_send_timeout 300; 

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

}

uvicorn and gunicorn are started using supervisor

supervisord.conf

[supervisord]
nodaemon=true

[program:fastapi_guni]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=/opt/venv/bin/gunicorn app.main:app --workers 4 --name main --worker-class /opt/venv/bin/uvicorn.workers.UvicornWorker --host 0.0.0.0:8000 --reload

the python main.py is

main.py

import uvicorn
from fastapi.middleware.cors import CORSMiddleware
from fastapi import FastAPI
from app.routes.api import router as api_router

app = FastAPI()

origins = ["http://localhost:8000"]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(api_router)

if __name__ == '__main__':
    uvicorn.run(host='127.0.0.1', debug=True, port=8000, log_level="info", reload=True)
    print("running")

when i try to bring up the containers, fastapi container will get stopped immediately once the container starts with the following message

fastapi exited with code 0

and nginx will also get stopped throwing the following message

nginx            | 2022/11/15 19:10:46 [emerg] 1#1: host not found in upstream "web:8000" in /etc/nginx/conf.d/app.conf:2
nginx            | nginx: [emerg] host not found in upstream "web:8000" in /etc/nginx/conf.d/app.conf:2
nginx exited with code 1

I am sitting on this for several hours and how can bring the service up and running.

update

Folder structure

enter image description here

Upvotes: 1

Views: 4251

Answers (1)

piyushere
piyushere

Reputation: 153

In the mentioned Dockerfile, I don't see any command for running the server. Something like this should work:

CMD ["python", "<path-to>/main.py"]

Also, to make it discoverable within the docker network, I had to run the application on '0.0.0.0' instead of localhost. (It might be an issue specifically on my system, But I didn't have time to debug that.)

Also, you should consider making the web service a dependency for nginx, so that nginx will start only after web is up and running.

Upvotes: 2

Related Questions