Search code examples
pythondockergunicornfastapiuvicorn

How to run FastAPI app on multiple ports?


I have a FastAPI application that I am running on port 30000 using Uvicorn programmatically. Now I want to run the same application on port 8443 too. The same application needs to run on both these ports. How can I do this within the Python code?

Minimum Reproducible code:

from fastapi import FastAPI
import uvicorn

app = FastAPI()


@app.get("/healthcheck/")
def healthcheck():
    return 'Health - OK'

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=30000)

I want to something like

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", ports=[30000,8443])

Explanation: My application will be running on my organizations Azure Kubernetes Service. Apps running on port 30000 are reserved for Internal HTTP traffic and apps running on 8443 are mapped to 443 of Kubernetes Service to be exposed to external traffic.

Further Details: I will be creating a Docker Container out of this application and the idea is to include

CMD ["python3", "app.py"]

at the end to run the application. I am looking for a solution that would either provide a way to change the python code ( uvicorn.run(app, host="0.0.0.0", ports=[30000,8443]) ) or a change to the CMD command in the Dockerfile like This GitHub Issue Comment - gunicorn -k uvicorn.workers.UvicornWorker -w 1 --bind ip1:port1 --bind ip2:port2 --bind ip3:port3


Solution

  • The following solution worked for me. It runs one gunicorn process in the background and then another process to bind it to two ports. One of them will use HTTP and one can use HTTPS.

    Dockerfile:

    FROM python:3.7
    WORKDIR /app
    COPY requirements.txt .
    RUN pip3 install -r requirements.txt
    COPY . .
    ENTRYPOINT ./docker-starter.sh
    EXPOSE 30000 8443
    

    docker-starter.sh:

    gunicorn -k uvicorn.workers.UvicornWorker -w 3 -b 0.0.0.0:30000 -t 360 --reload --access-logfile - app:app & gunicorn --access-logfile - -k --ca_certs ca_certs.txt uvicorn.workers.UvicornWorker -w 3 -b 0.0.0.0:8443 -t 360 --reload --access-logfile - app:app
    

    The python app can remain minimal:

    from fastapi import FastAPI
    import uvicorn
    
    app = FastAPI()
    
    
    @app.get("/healthcheck/")
    def healthcheck():
        return 'Health - OK'
    
    if __name__ == "__main__":
        uvicorn.run(app, host="0.0.0.0")