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:

25