This is a standard skeleton of a python ML project that I have built.
- web server/load balancer : nginx/traefik
- application server : gunicorn (WSGI)
- application server worker : uvicorn (ASGI)
- rest api layer : fastapi (async)
- db : postgres
- deployment : docker/docker-compose
Prerequisite:-
-
Install docker and docker-compose in your system.
-
Use this command to clone the repo (for Windows)
git clone https://github.com/tuhinsharma121/nginx-gunicorn-fastapi.git --config core.autocrlf=input
-
Use this command to clone the repo (for Unix)
git clone https://github.com/tuhinsharma121/nginx-gunicorn-fastapi.git
Steps to run the project:-
-
To run tests:
docker-compose -f docker-compose-test.yml build docker-compose -f docker-compose-test.yml up
Expected output
Creating network "nginx-gunicorn-fastapi_default" with the default driver Creating nginx-gunicorn-fastapi_db-test_1 ... done Creating nginx-gunicorn-fastapi_intel-test_1 ... done Attaching to nginx-gunicorn-fastapi_db-test_1, nginx-gunicorn-fastapi_intel-test_1 db-test_1 | db-test_1 | PostgreSQL Database directory appears to contain a database; Skipping initialization db-test_1 | db-test_1 | 2021-01-13 10:13:06.285 UTC [1] LOG: starting PostgreSQL 13.1 on x86_64-pc-linux-musl, compiled by gcc (Alpine 9.3.0) 9.3.0, 64-bit db-test_1 | 2021-01-13 10:13:06.285 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432 db-test_1 | 2021-01-13 10:13:06.285 UTC [1] LOG: listening on IPv6 address "::", port 5432 db-test_1 | 2021-01-13 10:13:06.295 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" db-test_1 | 2021-01-13 10:13:06.317 UTC [21] LOG: database system was shut down at 2021-01-13 10:12:04 UTC db-test_1 | 2021-01-13 10:13:06.337 UTC [1] LOG: database system is ready to accept connections intel-test_1 | ........... intel-test_1 | ---------------------------------------------------------------------- intel-test_1 | Ran 11 tests in 0.516s intel-test_1 | intel-test_1 | OK nginx-gunicorn-fastapi_intel-test_1 exited with code 0
Then bring it down:
docker-compose -f docker-compose-test.yml down
Expected output:
Removing nginx-gunicorn-fastapi_intel-test_1 ... done Removing nginx-gunicorn-fastapi_db-test_1 ... done Removing network nginx-gunicorn-fastapi_default
-
To bring the cluster up and running
Using traefik
docker-compose -f docker-compose-traefik-gunicorn-fastapi.yml build docker-compose -f docker-compose-traefik-gunicorn-fastapi.yml up -d --remove-orphans
Using nginx
docker-compose -f docker-compose-nginx-gunicorn-fastapi.yml build docker-compose -f docker-compose-nginx-gunicorn-fastapi.yml up -d --remove-orphans
Expected output:
Creating network "nginx-gunicorn-fastapi_intel_db_nw" with driver "bridge" Creating network "nginx-gunicorn-fastapi_nginx_intel_nw" with driver "bridge" Creating nginx-gunicorn-fastapi_db_1 ... done Creating nginx-gunicorn-fastapi_intel_1 ... done Creating nginx-gunicorn-fastapi_nginx_1 ... done
intel app - https://localhost:8008
swagger docs - https://localhost:8008/hxdocs
-
To scale intel app up to 3
docker-compose -f docker-compose-nginx-gunicorn-fastapi.yml up -d --scale intel=3 --no-recreate
Expected output:
Creating nginx-gunicorn-fastapi_intel_2 ... done Creating nginx-gunicorn-fastapi_intel_3 ... done
-
To check the logs
docker-compose -f docker-compose-nginx-gunicorn-fastapi.yml logs
-
To check the list of active containers
docker-compose -f docker-compose-nginx-gunicorn-fastapi.yml ps
Expected output:
Name Command State Ports -------------------------------------------------------------------------------------------------------- nginx-gunicorn-fastapi_db_1 docker-entrypoint.sh postgres Up (healthy) 0.0.0.0:5432->5432/tcp nginx-gunicorn-fastapi_intel_1 /bin/entrypoint.sh Up 0.0.0.0:49261->5678/tcp nginx-gunicorn-fastapi_intel_2 /bin/entrypoint.sh Up 0.0.0.0:49267->5678/tcp nginx-gunicorn-fastapi_intel_3 /bin/entrypoint.sh Up 0.0.0.0:49266->5678/tcp nginx-gunicorn-fastapi_nginx_1 /app/docker-entrypoint.sh ... Up 0.0.0.0:8008->80/tcp
-
To scale intel app down to 1
docker-compose -f docker-compose-nginx-gunicorn-fastapi.yml up -d --scale intel=1 --no-recreate
Expected output:
Stopping and removing nginx-gunicorn-fastapi_intel_2 ... done Stopping and removing nginx-gunicorn-fastapi_intel_3 ... done
-
To get inside a running docker container - intel
docker exec -it nginx-gunicorn-fastapi_intel_1 bash
Expected output:
root@2f1b3f7bb31d:/#
-
To bring the cluster down:
docker-compose -f docker-compose-nginx-gunicorn-fastapi.yml down
Expected output:
Stopping nginx-gunicorn-fastapi_nginx_1 ... done Stopping nginx-gunicorn-fastapi_intel_1 ... done Stopping nginx-gunicorn-fastapi_db_1 ... done Removing nginx-gunicorn-fastapi_nginx_1 ... done Removing nginx-gunicorn-fastapi_intel_1 ... done Removing nginx-gunicorn-fastapi_db_1 ... done Removing network nginx-gunicorn-fastapi_intel_db_nw Removing network nginx-gunicorn-fastapi_nginx_intel_nw