How to Deploy Django Applications on AWS EC2 Using Apache server.
Introduction
In this guide, we will walk through the steps to install and configure Django in a python virtual environment. After this, we will work on setting up an Apache server in front of our application for directly handling client requests, before passing the ones requiring application logic to the Django app. We will do this using the mod_wsgi Apache module that can communicate with Django over the WSGI interface specification.
What is the end Goal?
Our end goal is to make a connection between Django Web Server Gateway Interface(WSGI) to the Apache server to perfectly execute python code in the Django application, in a production environment using AWS EC2 instance as a cloud host service.
Outline of the post:
- SignUp into amazon web services.
- Launching an EC2 instance
- Configure EC2 instance ( Install Apache2, Pip, Apache module for WSGI, Virtual environment)
- Clone the Django project repository for GitHub.
- Create a Virtual Environment and Activate it.
- Install the requirement.txt file for necessary packages.
- Run application on the Django development server for testing.
- Now it’s time to configure Apache2 server to point to our Django application.
Basics Walkthrough.
What’s the Django Framework?
Django is a powerful Python web framework that helps us to develop web applications very easily. It is used to combine HTML/CSS, Javascript files for front-end, and python for the back-end. Django includes a simplified development server for testing our application on the local machine, but for slightly production-related work we need a more secure and powerful server.
What is the Web Server Gateway Interface(WSGI)?
Web Server Gateway Interface (WSGI) is just an interface specification with which, the server and application communicate.
A WSGI server only receives the request from the client, passes it to the application, and then sends the response returned by the application to the client.
Note: It is only used for Python Programming Language.
Apache is an example of an HTTP web server. An HTTP web server’s primary task is to receive a request, and serve HTTP files in response.
A module called mod-wsgi will be used to help Apache communicate with WSGI interface in our Django application.
What is AWS Elastic Compute Cloud (EC2)?
EC2 is a web service interface that provides virtual machines to run your application on a cloud platform. It is designed for developers to have complete control over web servers and computing resources.
Launching an AWS EC2 Instance
To start with AWS service, we need to sign up on aws.amazon.com.
After completing the sign-up process and logging into our AWS account, navigate to the services page, and choose EC2 from the Compute sub-menu.
From the EC2 dashboard, the Launch Instance portal will set up a new virtual machine server instance.
Launching a new instance is an 8 step process.
- Choose AMI (Amazon Machine Image)
Ubuntu Server 20.04 LTS (HVM), SSD Volume Type — ami-0e84e211558a022c0 Ubuntu Server 20.04 LTS (HVM), EBS General Purpose (SSD) Volume Type. Support available from Canonical.
2. Choose Instance Type.
3. Configure Instance Details.
4. Add Storage.
5. Add Tags
6. Configure Security Group.
Make sure to add at least the local machine’s IP to access the EC2 machine’s public DNS.
7. Review and Launch the Instance.
A key pair is generated after launching the instance. This key pair file helps in connecting to EC2 instance using SSH. This file is downloaded on to the system.
Connecting to EC2
Copy the SSH command which we will use to access the EC2 instance using the terminal.
Windows users might have to use Putty to connect SSH.
- In the local machine, navigate to the directory in the cmd/terminal where the key pair file is located.
- In cmd/terminal paste the SSH command that was copied previously and press yes if prompted with some local machine access permission
Till now, we have successfully established a connection with the EC2 Instance.
Install Packages from the Ubuntu Virtual Machine.
To begin the process, we’ll download and install all of the items we need from the Ubuntu virtual machine. This will include the Apache web server, the mod_wsgi module used to interface with our Django app, and pip (the python package manager), that can be used to download our Python-related tools.
If we are using Django with Python 2, the commands we need are:
$ sudo apt-get update$ sudo apt-get install python-pip apache2 libapache2-mod-wsgi
If instead, we are using Django with Python 3, we will need an alternative Apache module and pip package. In this case, the appropriate commands are:
$ sudo apt-get update$ sudo apt-get install python3-pip apache2 libapache2-mod-wsgi-py3
The First command is to update the apt package manager in Ubuntu. The second command is used to install apache2, pip3, and mod-wsgi
(module used in Apache, for running Django server).
Note: here sudo
is used to provide root access whenever necessary.
Configure a Python Virtual Environment
Now that we have the component from the ubuntu machine, we can start working on our Django project.
The first step is to create a Python virtual environment so that our Django project will be separated from the system tools and other python projects we may be working on.
Install the virtualenv
package using the following command.
If we are using Python 2, type:
$ sudo pip install virtualenv
If we are using Python 3, type:
$ sudo pip3 install virtualenv
With virtualenv
installed, we can start forming our project. Create a directory where we wish to keep our project and move into that directory.
$ mkdir django$ cd django
Here we will set up our virtual environment and also clone our Django application repository from GitHub.
Now, within the directory, create a Python virtual environment by typing:
$ virtualenv myenv
This will create a directory call myenv
within our Django directory.
Now clone the GitHub repository where our Django application located.
$ git clone “https://github.com/<username>/<repository name>.git”
In this article, the repository name is taken as firstproject
.
Before we will install our project’s Python requirements, we need to activate the virtual environment.
We can do this by typing:
$ source myenv/bin/activate
Our prompt should change to indicate that we are now operating within a Python virtual environment. It will look something like this: (myenv) user@host:~/django$.
Note: Whether we are using Python 2 or Python 3, when the virtual environment is activated, we should use pip
command(not pip3).
Running the Django development server.
We have to edit the settings.py
file of the Django project.
$ cd firstproject$ sudo vi firstproject/settings.py
The second command will open up the settings.py
file in vim editor.
Press I
to insert in the file, and insert the following line at the end of the file.
STATIC_ROOT = os.path.join(BASE_DIR, “sattic/”)
This line specifies the directory where all the static files of the application are located.
Also, we have to add instance’s DNS name/IP to “Allowed Hosts” in settings.py
.
ALLOWED_HOSTS = [‘EC2_DNS_NAME’]
Press Esc
key and type :wq
to save and close the file.
Now we are ready to install necessary requirements, run the following command:
$ pip install -r requirements.txt
A Django application may or may not have requirements.txt file. If not, please install the necessary dependencies to run your Django application without any error.
The most important dependency is Django which can be installed by running following command
$ pip install django
After installing necessary requirements from .txt file or running various commands manually, migrate the database, get static files ready, and test run the Django inbuilt development server.
$ python manage.py makemigrations$ python manage.py migrate$ python manage.py collectstatic$ python manage.py runserver 0:8000
In the browser, visit public DNS of the instance, make sure to append post “8000” at the end of the URL, and if everything goes fine we will see our Django application running in the browser.
http://server_domain_or_IP:8000/
This might work until the development server of Django is running. To resolve this issue, we use the Apache server to keep our development server running in the background, and respond to the user requests for file and data.
Configure Apache server.
To configure WSGI pass we’ll need to edit the default virtual host file:
$ sudo vi /etc/apache/sites-available/000-default.conf
To open the file in vim editor.
Press I
to start inserting to file.
To start, let’s configure the static files. We will use Alias to tell Apache to map any request starting with /static
to the “static” directory with our Django project folder.
<VirtualHost *:80>
. . .
Alias /static /home/ubuntu/django/firstproject/static
<Directory /home/ubuntu/django/firstproject/static>
Require all granted
</Directory></VirtualHost>
Next, we’ll grant access to the wsgi.py
file within the second level project directory where the Django code is stored.
<VirtualHost *:80>
. . .
Alias /static /home/ubuntu/django/firstproject/static
<Directory /home/ubuntu/django/firstproject/static>
Require all granted
</Directory>
<Directory /home/ubuntu/django/firstproject/firstproject>
<Files wsgi.py>
Require all granted
</Files>
</Directory></VirtualHost>
After this is configured, we are ready to construct the portion of the file that actually handles the WSGI pass. We’ll use daemon mode to run the WSGI process, which is the recommended configuration.
<VirtualHost *:80>
. . .
Alias /static /home/ubuntu/django/firstproject/static
<Directory /home/ubuntu/django/firstproject/static>
Require all granted
</Directory>
<Directory /home/ubuntu/django/firstproject/firstproject>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIDaemonProcess firstproject python- home=/home/ubuntu/django/myenv python-path=/home/ubuntu/django/firstproject WSGIProcessGroup firstproject WSGIScriptAlias / /home/ubuntu/django/firstproject/firstproject/wsgi.py</VirtualHost>
When we are finished making these changes, save and close the file by pressing Esc
and :wq
Wrapping Up Some Permissions Issues.
If you are using SQLite
database, which is the default used in this article, you need to allow the Apache process access to this file.
To do so, the first step is to change the permission so that the group owner of the database can read/write.
$ chmod 664 ~/firstproject/db.sqlite3$ sudo chown :www-data ~/firstproject/db.sqlite3$ sudo chown :www-data ~/firstproject
We need to adjust through our firewall.
$ sudo ufw delete allow 8000$ sudo ufw allow ‘Apache Full’
After all the configuration is done, check the Apache files to make sure we did not make any syntax errors:
$ sudo apache2ctl configtest
As long as the last line of output looks like this, our files are good in shape:
Output:
...
Syntax OK
Once these steps are done, we are ready to restart the Apache service to implement the changes we made.
Restart Apache by typing:
$ sudo systemctl restart apache2
In the browser, visit public DNS of the instance
http://server_domain_or_IP:8000/
It works!
This was just an example of how to set up Django with Apache on cloud service.
Reference: Django documentation