Home > Software design >  Dockerfile for a fastAPI app using Factory pattern with unicorn
Dockerfile for a fastAPI app using Factory pattern with unicorn

Time:04-04

I am building a back-end service for a full-stack application using fastAPI and unicorn.

src/asgi.py

import uvicorn
from src import create_app

app = create_app()

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", log_level="info", reload=True)

src/init.py

from fastapi import FastAPI
from src.api.v1.auth import auth_router
from src.core.config import *


def create_app() -> FastAPI:
    root_app = FastAPI()
    root_app.include_router(
        auth_router,
        prefix="/api/v1",
        tags=["auth"],
    )
    return root_app

Dockerfile

FROM python:3.9

RUN mkdir /app
WORKDIR /app

RUN apt update && \
    apt install -y postgresql-client

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

How I am building and running:

docker build -t travian-back:v1 . 
travian-back:v1 uvicorn asgi:app

There is no error at all, server is up at http://127.0.0.1:8000
Now I am trying to directly add the uvicorn asgi:app command to my Dockerfile. The reason is because I am going to use docker-compose at the end and it would be easier. This is what I have now:

Dockerfile

    RUN mkdir /app
    WORKDIR /app
    
    RUN apt update && \
        apt install -y postgresql-client
    
    COPY requirements.txt ./
    RUN pip install --no-cache-dir -r requirements.txt
    
    COPY . .

CMD ["uvicorn", "asgi:app"]

Now instead of doing travian-front:v1 uvicorn asgi:app I am doing travian-back:v1 uvicorn asgi:app , I have no error when building and running my docker image but the server can't be reached at http://127.0.0.1:8000

CodePudding user response:

The thing is that you don't run the asgi file as main, since you use uvicorn to point to it. So it's not listening on 0.0.0.0 or better put, all those options are ignored.

Either invoke the asgi file directly, which I would not recommend, or drop the asgi file and use uvicorn with the --factory flag and point it to your app factory.

ENTRYPOINT ["uvicorn", "src.init:create_app", "--factory", "--host 0.0.0.0"]

I am using entrypoint here so that you can pass additional flags such as log level on run without overriding this.

docker run -p 8000:8000 myapp --log-level warning

That said, I am somewhat confused by your file name init.py. Do you mean __init__.py? If so I would not put the factory in this file, __init__.py is not meant to be used like this. Put it in a file named main.py or similar.

  • Related