Deploy Django Project on EC2 using Nginx and uWSGI
Nginx is a high-performance web server that can handle a large number of requests efficiently. uWSGI is a fast and efficient application server that is well-suited for running Django applications. EC2 allows for easy scalability by enabling to scale application horizontally by adding or removing instances. This guide demonstrates how to deploy a Django project on EC2 using Nginx and uWSGI.
I. Create EC2 Ubuntu on AWS
- On AWS, create EC2 name “sudoku-3033”, connect to EC2 through terminal by this below command. Make sure open port 8000 on security group for local test.
ssh -i ~/sudoku-3033.pem ubuntu@ec2-18.XX.XX.147.ap-northeast-1.compute.amazonaws.com
If the connection fail due to Permission, run below command for grant read and write the publickey.
chmod 600 /Users/nguyenvanan2730/Projects/Sudoku-AWS/sudoku-info/pro-sudoku/sudoku-3033.pem
- After login in EC2, run below command for update package list.
sudo apt update sudo apt upgrade
II. Create Virtual Environment, and install necessary library
Create Virtual Environment
- Install pip3:
sudo apt install python3-pip
- Install virtualenv for create virtual environment
sudo apt install python3-virtualenv
- Create virtual environment in root direction home/ubuntu
virtualenv venv
- Activate environment
source venv/bin/activate
After the virtual environment is activated, the format on terminal will be displayed like: (venv) ubuntu@ip-10-0-4-232:
Clone project from GitHub
- Update git using version 2.34.1
sudo apt install git
- Clone source code from GitHub using "git clone and token"
git clone https://nguyenvanan2730:<token>@github.com/nguyenvanan2730/sudoku.git
Install necessary library
- Django
pip3 install django==4.1.4 pip3 show Django -->4.1.4
- Numpy
pip3 install numpy==1.23.5 pip3 show numpy -->=1.23.5
- opencv
pip3 install opencv-python==4.6.0.66 pip3 show opencv-python -->4.6.0.66 sudo apt-get install libgl1-mesa-glx --> Install this packages for successful import OpenCV
- boto3
pip3 install boto3==1.26.30 pip3 show boto3 --> 1.26.30
- Pillow
python3 -m pip install Pillow
- django-environ
python3 -m pip install django-environ
- aws-cli
sudo apt install awscli
III. Setting Variable Environment
- Create a .env file in the /home/ubuntu/venv/sudoku/sudoku_project
sudo nano /home/ubuntu/venv/sudoku/sudoku_project/.env
-
Setting below content in the .env file
MEDIA_ROOT=/home/ubuntu/venv/sudoku/sudoku_project/media MEDIA_URL=/image/ IMAGE_UPLOAD_PATH=/home/ubuntu/venv/sudoku/Images/crop-input-image IMAGE_TRANSFORM_CROP=/home/ubuntu/venv/sudoku/Images/crop-input-image STATIC_ROOT=/home/ubuntu/static DEBUG=FALSE ALLOWED_HOSTS=18.XX.XX.147
The static_root setting is the absolute filesystem path to the directory where all collected static files will be stored after running the collectstatic command. The collectstatic command is used to gather static files from various locations and place them in a single location for easier deployment and improved performance. -
Create a .gitignore file and add .env into it, ensure that do not push these configure to the GitHub.
.env db.sqlite3 mysite.sock uwsgi_params media/
Run below command, the screen should be display as http://18.XX.XX.147:8000python manage.py runserver 0.0.0.0:8000
IV. Deploy application on EC2 using Nginx and uWSGI
Install uWSGI into virtualenv
- Activate the virtual environment and run below command to install uWSGI.
pip install uwsgi
uWSGI will be located at /home/ubuntu/venv/lib/python3.10/site-packages. Can check if the uWSGI is installed by running "pip freeze" or "pip3 show uWSGI" - After uWSGI is successful installed, Django can run the following command. Access sever through the browser, application should be executed as run python3 manage.py runserver 0.0.0.0:8000 command.
uwsgi --http :8000 --module sudoku_project.wsgi
sudoku_project.wsgi is not a file but a reference to the application instance located in the wsgi.py file. As uWSGI was not yet configured to serve static files, the screen design may appear broken at this stage. In the next step, static files will be served using Nginx.
Configure Nginx as Web Server
- Install and start Nginx using below command.
sudo apt-get install nginx. # install nginx sudo service nginx start # start nginx
After Nginx is started, the message “Welcome to nginx” should be displayed at the address: http://18.XX.XX.147:80 - Configure Nginx for project
Create a uwsgi_params file in ~/venv/ contains below configures.
uwsgi_param QUERY_STRING $query_string; uwsgi_param REQUEST_METHOD $request_method; uwsgi_param CONTENT_TYPE $content_type; uwsgi_param CONTENT_LENGTH $content_length; uwsgi_param REQUEST_URI $request_uri; uwsgi_param PATH_INFO $document_uri; uwsgi_param DOCUMENT_ROOT $document_root; uwsgi_param SERVER_PROTOCOL $server_protocol; uwsgi_param REQUEST_SCHEME $scheme; uwsgi_param HTTPS $https if_not_empty; uwsgi_param REMOTE_ADDR $remote_addr; uwsgi_param REMOTE_PORT $remote_port; uwsgi_param SERVER_PORT $server_port; uwsgi_param SERVER_NAME $server_name;
Create a mysite_nginx.conf in the /etc/nginx/sites-available/ directory.# mysite_nginx.conf # the upstream component nginx needs to connect to upstream django { server unix:///home/ubuntu/venv/sudoku/sudoku_project/mysite.sock; # for a file socket #server 127.0.0.1:8001; } # configuration of the server server { # the port your site will be served on listen 8000; # the domain name it will serve for server_name 18.XX.XX.147; # substitute your machine's IP address or FQDN charset utf-8; # max upload size client_max_body_size 75M; # adjust to taste # Django media location /media { alias /home/ubuntu/venv/sudoku/sudoku_project/media; # your Django project> } location /static { alias /home/ubuntu/venv/sudoku/sudoku_project/static; # your Django project> } # Finally, send all non-media requests to the Django server. location / { uwsgi_pass django; include /home/ubuntu/venv/uwsgi_params; # the uwsgi_params file you ins> } }
-
Run below command, uWSGI and Nginx should be serving as expected.
uwsgi --socket mysite.sock --module sudoku_project.wsgi --chmod-socket=664
Configuring uWSGI to run with a .ini file
- Create a file call mysite_uwsgi.ini in the ~/venv/ direction
# mysite_uwsgi.ini file [uwsgi] # Django-related settings # the base directory (full path) chdir = /home/ubuntu/venv/sudoku/sudoku_project # Django's wsgi file module = sudoku_project.wsgi # the virtualenv (full path) home = /home/ubuntu/venv # process-related settings # master master = true # maximum number of worker processes processes = 10 # the socket (use the full path to be safe socket = /home/ubuntu/venv/sudoku/sudoku_project/mysite.sock # ... with appropriate permissions - may be needed chmod-socket = 664 # clear environment on exit vacuum = true
-
And Run uwsgi using this file, the same result will be displayed on the screen.
uwsgi --ini /home/ubuntu/venv/mysite_uwsgi.ini
Install uWSGI system-wide
-
# Deactivate virtualenv: deactivate #Install uWsGI system-wide sudo pip3 install uwsgi #Run uWSGI again in the global environment uwsgi --ini /home/ubuntu/venv/mysite_uwsgi.ini
uWSGI is only installed in the virtualenv, install uWSGI in global environment for deployment.
Emperor mode
"Emperor mode" in Nginx and uWSGI refers to a feature that allows Nginx to run as a master process and manage multiple uWSGI worker processes. In this mode, Nginx acts as a reverse proxy and load balancer for the uWSGI worker processes, and can automatically start, stop, and respawn the worker processes as needed.
-
Create a directory name vassals, -p option means the parents directories will be created if it do not already exist.
sudo mkdir -p /etc/uwsgi/vassals
-
Create a symlink from the default config directory to your config file
sudo ln -s /home/ubuntu/venv/mysite_uwsgi.ini /etc/uwsgi/vassals/
-
Run uWSGI again with sudo
sudo uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data
Make uWSGI startup when the system boots
-
Create "emperor.uwsgi.service" file at: /etc/systemd/system/emperor.uwsgi.service
[Unit] Description=uwsgi emperor for micro domains website After=network.target [Service] User=ubuntu Restart=always ExecStart=sudo uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data [Install] WantedBy=multi-user.target
-
After setting emperor.uwsgi.service file, enable and start service. It is should show the results like run Emperor mode.
sudo systemctl enable emperor.uwsgi.service sudo systemctl start emperor.uwsgi.service
-
Now, reboot server and the application should be startup. Below command can be used in emperor.uwsgi.service
sudo systemctl enable emperor.uwsgi.service sudo systemctl start emperor.uwsgi.service sudo systemctl status emperor.uwsgi.service sudo systemctl stop emperor.uwsgi.service sudo systemctl restart emperor.uwsgi.service
This guide has demonstrated the steps for deploying a Django application to EC2 using Nginx and uWSGI. However, in other to make the project accessible via sudokusolver.click, additional configuration on the AWS is required. For more informations about this topic, consult the documentation at System Architect.