Deploy Django app on AWS
Deploy and host a django application on AWS EC2 instance using Nginx as the webserver
and Gunicorn as WSGI
Nginx is an open-source web server that, since its success as a web server
, is now also used as a reverse proxy
, HTTP cache
, and load balancer
.
WSGI used to forward request from a web server to a python backend.
Please Refer: HTTP request-response lifecycle
1. Initial setup
Create EC2 instance
Create/Launch EC2 instance: /tags/ec2/
- Enable ssh to server - to connect to EC2 server
EC2 > security group > Edit inbound rules > Allow SSH
Connect to EC2 instance
# Connect
ssh -i "name.pem" ubuntu@host
Install the latest patch of python 3.6
Python and PIP installation: /tags/python-setup/
Update and install python-pip and virtualenv
sudo apt-get update && sudo apt-get -y upgrade && sudo apt install python3-pip
2. Install git and configure user and email and clone repo
# Install
sudo apt-get install git-core
# Configure
git config --global user.name "Amrit"
git config --global user.email "[email protected]"
# Clone Repo
git clone -b aws-django https://github.com/amrit94/deployment-demo.git
- Fix clone/update issue
sudo apt install gh
gh auth login
gh repo clone amrit94/deployment-demo
3. Make virtual-env and install requirements.txt
# Install
pip install virtualenv
sudo apt install python3.8-venv
# Make Venv
mkdir ~/.virtualenvs/
cd ~/.virtualenvs/
python3.6 -m venv testvenv
# Activate venv
source ~/.virtualenvs/testvenv/bin/activate
# Install all requirements.txt
cd ~/deployment-demo/
pip install -r requirements.txt
Issue
# psycopg2 --> installation issue
pip install psycopg2-binary
sudo apt install libpq-dev
# Python.h issue
sudo apt install libpython3.6-dev
4. Setup Database
4.1 Install Postgresql and configure new role and grant all permissions
sudo apt-get install postgresql
sudo /etc/init.d/postgresql start
sudo -u postgres psql
postgres=# CREATE DATABASE testdb;
postgres=# CREATE ROLE testuser WITH LOGIN PASSWORD 'password';
postgres=# GRANT ALL PRIVILEGES ON DATABASE testdb TO testuser;
4.2 OR Install Mysql and add new user with all the privileges
sudo apt-get update
sudo apt-get install mysql-server (Remember the password entered for root user)
mysql_secure_installation
mysql -u root -p
mysql> CREATE DATABASE testdb;
mysql> CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON * . * TO 'testuser'@'localhost';
mysql> \q
sudo apt-get install python-mysqldb
mysql -u testuser -p (Now you are logged in as testuser user)
4.3
python manage.py migrate
5. Test your server
Django has inbuilt webserver
, it is used in development server but not in production, because
- Single-threaded server`
- Can serve only one request at a time
Test - Is the application working properly
- Update Security group -
For test allow all traffic
- EC2 > security group > Edit inbound rules > Map: All traffic to Anywhere
python manage.py runserver 0.0.0.0:8000
- Visit
- http://public_ip:8000/
- http://public_ip:8000/admin
By using inbuilt webserver there will be no issue to access static file
5. Setup Gunicorn
pip install gunicorn
5.1 Testing Gunicorn’s Ability to Serve the Project
gunicorn --bind 0.0.0.0:8000 kharchapani.wsgi
Visit:
http://public_ip:8000/
Static files are directly not accessible for --bind 0.0.0.0:8000
.
To Enable add below line to access
# seting.py
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# urls.py
from django.conf.urls.static import static
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
5.2 Setup gunicorn to run as a service
5.2.1 Create a Gunicorn systemd Service File
# sudo vim /etc/systemd/system/gunicorn.service
# Add below line in 'gunicorn.service' file
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/Deployment-demo
ExecStart=/home/ubuntu/.virtualenvs/testenv/bin/gunicorn --workers 3 --bind 0.0.0.0:8000 blogpost.wsgi:application
[Install]
WantedBy=multi-user.target
5.2.2 Start the server
- Start the server and check the status
sudo systemctl start gunicorn
sudo service gunicorn status
- Enable the server to automatically start at boot
sudo systemctl enable gunicorn
5.2.3 Restart gunicorn
If you make changes to the /etc/systemd/system/gunicorn.service file, reload the daemon
to reread the service definition
and restart the Gunicorn process by typing
sudo systemctl daemon-reload
sudo systemctl restart gunicorn
- Check
gunicorn process logs
by typing
# from start
sudo journalctl -u gunicorn
# live logs
sudo journalctl -f -u gunicorn
- Try
Visit:
http://public_ip:8000/
6. Setup Nginx
sudo apt-get install nginx
Update ExecStart of gunicorn.service
# sudo vim /etc/systemd/system/gunicorn.service
ExecStart=/home/ubuntu/.virtualenvs/testvenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/ubuntu/Deployment-demo/myproject.sock myproject.wsgi:application
Configure Nginx to Proxy Pass to Gunicorn
# sudo vim /etc/nginx/sites-available/kharchapani
server {
listen 80;
server_name public_ip_address;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/ubuntu/kharchapani;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/kharchapani/kharchapani.sock;
}
}
Enable the file by linking it to the sites-enabled directory:
sudo ln -s /etc/nginx/sites-available/kharchapani /etc/nginx/sites-enabled
- Visit:
- http://public_ip
sudo nginx -t
sudo systemctl restart nginx
sudo tail -F /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
7. Domain Mapping
A domain_name ip_address
Update nginx setting
# sudo vim /etc/nginx/sites-available/kharchapani
server_name replace_this_with_domain_name;
Production Security group
- Update Security group -
Only HTTP, HTTPS and SSH traffic
- EC2 > security group > Edit inbound rules > Map: All traffic to Anywhere
8. Initial Server Setup with Ubuntu
- Will ignore this for now
Reference
- https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04
- https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04
- https://medium.com/analytics-vidhya/deploying-django-apps-e2f4d4f355a1
- https://medium.com/saarthi-ai/ec2apachedjango-838e3f6014ab
- https://www.freecodecamp.org/news/django-uwsgi-nginx-postgresql-setup-on-aws-ec2-ubuntu16-04-with-python-3-6-6c58698ae9d3/