How to deploy any Python Web Application?

Hey everyoneπŸ‘¨β€πŸ’»
In this blog post I will explain how you can deploy any ASGI/WSGI compliant Python Web App.

DISCLAIMER:

Only ASGI Compliant Frameworks can be deployed using this method, other frameworks can't be deployed.

List of Tools I will be using:

  • NGINX
  • Hypercorn
  • FastAPI

Now here, there are alternatives to Hypercorn and FastAPI

Alternatives to Hypercorn:

  • Gunicorn
  • Uvicorn
  • Daphne

Other Frameworks that can be deployed:

  • Flask
  • Django
  • Starlette
  • Any ASGI/WSGI compliant framework

Step One:

Setup your framework using the docs mentioned.

Since I'll be using FastAPI, my main.py looks like this

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def hello_world():
   return f"Hello World"

πŸš€ We now have a FastAPI app ready, we now have to deploy it using NGINX. βš™οΈ

Step Two:

Depending upon your framework and choice of ASGI/WSGI Server, this process will be slightly different.

For Django Devs:

Your wsgi/asgi application would be called as <application_name>.<a/w>sgi:application
Choose ASGI or WSGI clearly and stay with that option throughout

For Flask Devs:

If your app is in main.py, it would be called as main:app

In this step we'll be binding the web-server to UNIX socket. Learn more about UNIX Sockets. here

I am attaching the docs of Daphne, Uvicorn and Gunicorn down which use different flags to bind the application to a port.

Run this command to bind it to the socket

hypercorn -b 'unix:/var/tmp/hypercorn.sock' -w 4 main:app

In this -w defines the number of workers.
Change hypercorn.sock to the server which you choose to use.

Change the socket name according to your web server

πŸŽ‡ Now we have our app listening on the hypercorn.sock.

Step Three:

We've to proxy this socket to NGINX and route NGINX to listen to the hypercorn socket.

worker_processes 1;
events {
  worker_connections 512;
}
http {
  server {
    listen 8080;
    server_name "localhost";
    access_log /var/log/nginx/access.log;
    error_log /var/log/error.log ;
    location / {
      proxy_pass http://unix:/var/tmp/hypercorn.sock;
    }
   }
}

I'll briefly explain this config file:

  • Worker_processes => 1 worker process has been assigned for this specific task/process
  • Worker connections => Number of connections that can be handled by 1 process
  • Listen => Listens at the mentioned port
  • Server Name => Listens at this domain
  • Access_log => The file location at which access log is stored, access log stores requests made
  • Error_log => The file location at which error log is stored.
  • Proxy Pass => The socket/port which needs to be proxied.

This file should change based on your socket but the other configuration can be the same.

πŸš… Save this file as nginx.conf

Feel free to read about NGINX here

Once this file is made, save it at /etc/nginx/

Either you can use docker to run a Linux server or shell into an instance.

If you want to copy it to docker.

COPY nginx.conf /etc/nginx/

πŸ’£ You are ready to launch except one last step

Step four

  • You have now wonderfully setup your web-server and the NGINX proxy πŸ™Œ
  • You are just one-step away from accessing the port, and perhaps this is the βœ… or ❌ step

Currently, NGINX can't read or write from the socket, so we need to change access mode

To do this, run the following command:

chmod 777 /var/tmp/<socket> 
sudo service nginx restart

🌟Now you can listen from the port 8080, http://localhost:8080

If you are using systemctl, please use this command instead:

sudo systemctl restart nginx

Play around with NGINX config as you wish based on your application's requirements.

Thanks for readingπŸ§‘β€πŸš€

Docs:

26