Django's foremost aim is to reduce the creation of complex, database-driven websites. The framework highlights the reusability and "pluggability" of components, less code, low coupling, fast development, and the principle of don't repeat yourself.

Django is a python-based free and open-source web framework, which follows up the model-template-view or we can call it as (MTV) architectural pattern. Django subsumes a simplified development server for testing your code locally. Furthermore, it demands a more secure and powerful web server. This article explains about various steps to deploy Django application on Amazon Web Server using nginx and gunicorn.

  • Creating an instance in Amazon Web Server
    1. Go to https://aws.amazon.com and create a new account if you don't have any or log in to your existing account.
    2. Click on Services and go to the Compute section and select EC2.
    3. Go to Create Instance section and click on Launch Instance.
    4. Now choose an Amazon Machine Image (AMI), here I have used Ubuntu Server 16.04 LTS 64-bit (x86).
    5. Now choose an Instance Type, select t2.micro because it is free tier eligible, then click on Review and launch button.
    6. Now, you will land on Review Instance Launch. In this step click on launch. Here a pop-up appears for selecting key-pairs (it is a security key). You can select an existing key-pair if you have or create one if you don't have. Click on launch instance. It will create and download a .pem file. Keep this file secure and place it in a directory which you can use later on while running your project.
    7. Finally, your instance is launched. For viewing it, go to Services>Compute >EC2 and select "Running Instances". It will show you all the running instances.
    8. Now select your instance and under security groups column, click on launch-wizard.
    9. Now under the inbound tab, select edit and further click on "Add Rule". You will find SSH rule already presents there. Add three more rules. When you click on add rule button, you will find a new appended row to the existing ones with type "Custom TCP". In this row add port number 8000 (Django and unicorn uses 8000 port default) and then add two more rules. One for HTTPS and another for HTTP. Finally hit the save button.
    10. Now again select your instance from the dashboard and copy Public DNS(ipV4) and IPV4 Public IP. Keep these two descriptions safe for future use.

  • Connect with your instance and upload files in it
    1. Now select your instance and click on the "Actions" button and then select connect.

    A pop will appear showing commands to access your instance. Now open a terminal and go to the directory where you have placed your .pem file. and run the following command. This is basically for giving the required permissions.

    Desktop$ chmod 400 yourfile.pem
    

    Then, copy example command from the same pop-up and run in terminal.

    Desktop$ ssh -i "rajat4665.pem" ubuntu@ec2-52-14-64-58.us-east2.compute.amazonaws.com
    
    1. When your terminal user name is converted to ubuntu@ip-XXX-XX-XX-XX it means you are connected to your instance.
    2. Download Filezilla. It is available for both windows and ubuntu. Here I downloaded it from the ubuntu software app store.
    3. Now open Filezilla. First, go to Edit and select preferences and go to SFTP and click on add key file. Here you have to add your key pair (.pemfile ). Paste IPV4 Public IP (description of instance) in the host, enter the user name "ubuntu" and leave the password blank, then enter port number 22 (default port of SFTP is 22). Finally, click on quick connect and then press ok. Now your server is connected to your local system.
    4. Open your project on your computer. Paste static and templates folders inside the app folder.
    5. Now on the left side of Filezilla dashboard is your local pc directories and on  the right side is your

  • Configure your remote server, setup gunicorn, and Nginx
    1. Enter following command:
    sudo apt update
    
    sudo apt upgrade
    

    if any pop-up appears while upgrading click on default option.

    sudo apt install python3-pip python3-dev libpq-dev postgresql postgresqlcontrib nginx curl
    

    Install, create and activate the virtual environment

    1. Installing a virtual environment

     sudo apt install python3-venv

    2. Creating a virtual environment

      python3 -m venv ./myenv

    3. Activating virtual environment

    cd myenv
    cd bin
    source activate
    

    Now you can see your terminal user is connected with the prefix of (myenv), this means your virtual environment activated successfully.

    4. Now create a text file with name "requirements" (You can give any other name also)

    touch requirements.txt
    sudo nano requirements.txt
    

    then paste the following details they're and save it.

    Django==2.1.4
    gunicorn==19.9.0
    Pillow==5.3.0
    psycopg2==2.7.6.1
    psycopg2-binary==2.7.6.1
    pytz==2018.7
    requests==2.21.0
    urllib3==1.24.1
    

    Before executing this file, type this command

    pip3 freeze
    

    It will display installed packages in the virtual environment. Now we need to install requirements.txt file through terminal. First go to file location and run following command:

    pip3 install -r requirements.txt
    

    Edit setting.py file in the remote server

    Open the project folder in your remote server. Here, my project folder name is "weather". Go to weather folder (inside main weather folder) and open setting.py

     sudo nano setting.py
    

    Now, comment the following lines if they are present.

    #STATIC DIR=(os.path.join(BASE DIR,'static'))
    #print(STATIC DIR)
    #STATICFILES DIRS = [
    # STATIC DIR,
    #]
    

    then paste these two lines at the end of setting.py file

    STATIC URL = '/static/'
    STATIC ROOT = os.path.join(BASE DIR, "static/")
    

    Copy your IPV4 Public IP from amazon instance and paste it in "ALLOWED HOST" in setting.py file.

    ALLOWED HOSTS = [ ]
    

    Put your IPV4 Public IP in it.

    ALLOWED HOSTS = ['52.14.64.58'] (like this)
    

    Now press ctrl+o for saving and hit enter. For exiting, press ctrl + x.

    Now we need to Create static files(make sure that no static files are placed in main

    project folder . It should be in app folder). Run following command in main project

    folder:

    python3 manage.py collectstatic
    

    It will create a folder named "static" in your main project folder.

    Now you can check whether your remote server is working or not. Run this command

    and paste your IPV4 Public IP:8000 in a web browser.

    python3 manage.py runserver 0.0.0.0:8000
    

    Open browser XX.XX.XX.XX:8000. Here 8000 is your port number. Now you can

    view your project running on a web-browser. Use ctrl + c to exit from a local server

    running in the terminal.

    2. Configuring Gunicorn: Now Test your Gunicorn server in the main project folder.

    gunicorn {bind 0.0.0.0:8000 weather.wsgi
    

    I put the weather. wsgi because the weather is my project name. Now you can check it

    through your browser XX.XX.XX.XX:8000 (XX.XX.XX.XX is the IPV4 Public IP

    of your amazon EC2 instance ). If it working then press ctrl+c to deactivate.

    Run this command to open gunicorn.socket file</p>

    sudo nano/etc/systemd/system/gunicorn.socket
    

    Copy this code, paste it and save.

    [Unit]
    Description=gunicorn socket
    [Socket]
    ListenStream=/run/gunicorn.sock
    [Install ]
    WantedBy=sockets.target
    

    Run this command to Open gunicorn.service file

      sudo nano /etc/systemd/system/gunicorn.service
    

    Copy this code, paste it and save.

    [Unit]
    Description= gunicorn daemon
    Requires= gunicorn.socket
    After= network.target
    [Service]
    User= ubuntu
    Group= www-data
    WorkingDirectory= /home/ubuntu/myproject/weather
    ExecStart=/home/ubuntu/myproject/myenv/bin/gunicorn   \
    {access-logfle -  \
    {workers 3   \
    {bind unix:/run/gunicorn.sock   \
    weather.wsgi:application
    [Install]
    WantedBy=multi-user.target
    

    WorkingDirectory= is your pwd of project folder ExecStart = gunicorn directory. Now we Start and enable Gunicorn socket. Enter following commands :

    sudo systemctl start gunicorn.socket
    sudo systemctl enable gunicorn.socket
    				
    

    Now we have to check status of gunicorn. Enter following commands :

    sudo systemctl status gunicorn.socket
    

    Check the existence of gunicorn.sock. Enter following commands :

      file /run/gunicorn.sock
    

    NGINX Setup:

    Create nginx files using following command under main project folder(weather in this case):

    sudo nano /etc/nginx/sites-available/weather
    

    Copy this code, paste it and save

    server {
    listen 80;
    server name 52.14.64.58;
    location = /favicon.ico f access log off; log not found off; }
    location /static/ {
    root /home/ubuntu/myproject/weather;
    }
    location / {
    include proxy params;
    proxy pass http://unix:/run/gunicorn.sock;
    }
    }
    

    If there is a media file in your django project, go to this link https://gist.github.

    com/bradtraversy/cfa565b879ff1458dba08f423cb01d71 and copy above step.

    Now enable the file by linking to the sites-enabled dir via terminal.

    sudo ln -s /etc/nginx/sites-available/weather /etc/nginx/sites-enabled
    

    Test NGINX configuration by entering following command:

    sudo nginx -t   //test is successful
    

    Now we need to Restart NGINX and Gunicorn.

    sudo systemctl restart nginx
    sudo systemctl restart gunicorn
    

    Now you can check in browser whether your project is working on IPV4 Public IP (on this address). Now you need not run server manually.

    Domain Setup:

    Go to local settings.py on the server and change "ALLOWED HOSTS" to include the domain.

    ALLOWED HOSTS = ['IP ADDRESS', 'example.com','www.example.com']
    

    Edit nginx configuration

    /etc/nginx/sites-available/weather
    server {
    listen: 80;
    server name xxx.xxx.xxx.xxx example.com www.example.com;
    }
    
    

    Now go to DNS management in your domain and fill your IP details.

    Important steps:

    - Now configure amazon instance with your DNS

    - Go to services and select Networking & Content Delivery section and click on

    Route 53

    - Click on a hosted zone

    - Now click on create hosted zones enter your domain details and paste your IPV4

    Public IP in value followed by .(dot) like XX.XX.XX.XX. save it

    Signing Off

    Django subsumes a simplified development server for testing your code locally. We hope this post helps you throughout the right test case class in your Django project. To stay in touch and not miss any of our articles/blogs, then do subscribe to our newsletter, follow us on medium.com and check out our blog page https://blog.paradisetechsoft.com/.

    References

    https://gist.github.com/bradtraversy/cfa565b879ff1458dba08f423cb01d71

    https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/django_assessment_blog