Deploy a python django and reactJS restful app with gunicorn, supervisor and nginx on a linux ubuntu server.
King Isaac Nsengiyunva
Posted on July 5, 2022
The task is to deploy a decoupled Application with 2 seperate services that communicate with each other using API. The frontend app written with ReactJS - a popular Javascript library - and a backend app that handles the database written in Python using the Django restframework library. The 2 apps are also hosted on the github server repository.
The React app communicates with the Django/ Server over REST HTTP methods such as POST, GET, PUT, PATCH, DELETE etc.
Step 1: staging the apps on the server
- Git clone your django app on the Ubuntu server e.g.
$ git clone https://github.com/<your username>/<your git repo>
- Git clone your reactJS app too. You should have 2 folders listed on the server with all the files.
Step 2: Manual compile and prepare the reactJS frontend.
-
$ cd
into your reactJS frontend folder by typing.cd <frontend folder name>
-
$ yarn install
or$ npm install
to add dependencies and packages to your app. ifyarn
ornode
is not installed on the ubuntu server, make sure you install these libraries first. -
$ yarn run build
to transpile the final static and bundled files. - Your frontend app will now include a
build
folder with the static and bundled files.
Step 3: Staging and Preparing the Django app
- Create a new virtual environment for the django app by running
python3 m venv <virtual env name>
- Activate the virtual environment by running:
source <virtual env name>/bin/activate
- Install all dependencies for the django app by running:
pip install -r requirements.txt
- Install Gunicorn if not already installed by running:
pip install gunicorn
Step 4: Create a Gunicorn shell script to execute the django app
- Change user to root by logging as root user.
- Create a gunicorn shell script preferably in the same folder as the django app e.g. gunicorn.sh.
- An example draft template of this gunicorn script should look like this:
#!/bin/bash
NAME="<service name>" #name of the service to be run by supervisor
DJANGODIR=<path/to/django app>
USER=<user e.g. root> #you can see your user name by running command whoami
GROUP=<usergroup e.g. root>
NUM_WORKERS=<number of workers e.g. 2>
TIMEOUT=<e.g 500>
DJANGO_SETTINGS_MODULE=<app.settings<the django settings file>>
DJANGO_WSGI_MODULE=<app.wsgi< the wsgi file>>
PORT=<8500>
LOCAL_IP=<127.0.0.1>
echo "Starting $NAME as `whoami`"
cd $DJANGODIR
source <path/to/virtualenv/bin/activate> #run the virtual environment
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE #set the global variable to the settings file
export PYTHONPATH=$DJANGODIR:$PYTHONPATH #set your django app directory as python path
exec <path/to/virtualenv/bin/gunicorn ${DJANGO_WSGI_MODULE} >
--name $NAME \
--workers $NUM_WORKERS \
--timeout $TIMEOUT \
--user=$USER --group=$GROUP \
--pythonpath=<path/to/virtualenv/bin \
--log-level=debug \
--bind=$LOCAL_IP:PORT \
--logo-file=-
- Run the gunicorn shell script by executing
./gunicorn.sh
Step 5: Configure the Supervisor
- Supervisor in this case scenario is responsible for running the django service. Before you proceed, make sure the
supervisor
library /package is correctly installed on the Ubuntu VPS. - check the current service list by running
$ sudo supervisorctl status
This will display a list of service names available. - Add a New Service as set in the
gunicorn.sh
script above by navigating to$ cd /etc/supervisor/conf.d
. Then create your service conf file e.gsudo nano <name.conf>
- To update the supervisor list. Run
supervisorctl reread
. This command will make your configuration changes available.
Step 6: Add Nginx to serve the applications
- Nginx will serve both our applications on the default port 80. Make sure the nginx library or package is installed on the Ubuntu machine.
- Navigate to the nginx folders as:
$ cd /etc/nginx/sites-available
and create a new conf file for your application configuration. - Create a conf file as
<sudo nano name.conf>
- Add a server block as shown below:
server {
server_name <name/your preferred domain name>;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
location / {
root /path/to/react/frontend/build;
}
location /api/v1 {
proxy_pass http://<localhost>:<port name configured in gunicorn shell script >;
}
}
- The server block above shows includes 2 location directives.
- The root folder directive serves the reactjs build folder that includes the index.html file.
- The location directive
<server name/ap1/v1>
will serve the django rest server using a proxy pass address.
Happy Coding!
Posted on July 5, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.