Deploying Django to AWS with Docker and Let's Encrypt

In this tutorial, we'll deploy a Django app to AWS EC2 with Docker. The app will run behind an HTTPS Nginx proxy that uses Let's Encrypt SSL certificates. We'll use AWS RDS to serve our Postgres database along with AWS ECR to store and manage our Docker images.

Django on Docker Series:

  1. Dockerizing Django with Postgres, Gunicorn, and Nginx
  2. Securing a Containerized Django Application with Let's Encrypt
  3. Deploying Django to AWS with Docker and Let's Encrypt (this tutorial!)

Objectives

By the end of this tutorial, you'll be able to:

  1. Set up a new EC2 instance
  2. Install Docker on an EC2 instance
  3. Configure and use an Elastic IP address
  4. Set up an IAM role
  5. Utilize Amazon Elastic Container Registry (ECR) image registry to store built images
  6. Configure AWS RDS for data persistence
  7. Configure an AWS Security Group
  8. Deploy Django to AWS EC2 with Docker
  9. Run the Django app behind an HTTPS Nginx proxy with Let's Encrypt SSL certificates

Prerequisites

This post builds on the Dockerizing Django with Postgres, Gunicorn, and Nginx and Securing a Containerized Django Application with Let's Encrypt posts.

It assumes that you can:

  1. Containerize a Django app along with Postgres, Nginx, and Gunicorn.
  2. Secure a containerized Django app running behind an HTTPS Nginx proxy with Let's Encrypt SSL certificates.
  3. Use SSH to connect to a remote server and SCP to copy files over to the server.

AWS EC2

First, create an AWS account if you don't already have one.

Next, navigate to the EC2 console and click Launch instance:

EC2 Home

Enter a name for your instance and select Ubuntu Server 22.04 LTS (HVM) for the server image (AMI):

Select AMI

Stick with the t2.micro instance:

EC2 instance type

Create a new key pair for accessing your instance via SSH by clicking on "Create new key pair". When configuring the security group, stick with the default "Create new security group" and select "Allow HTTPS traffic from the internet" and "Allow HTTP traffic from the internet":

EC2 configure security group and add new key pair

These rules are needed to issue certificates and to access the app.

The key pair will automatically download upon created.

Security group inbound rules are used to limit access to your instance from the internet. Unless you have some additional security requirements, you'll probably want to allow HTTP and HTTPS traffic from anywhere for instances hosting web apps. SSH must be allowed for you to connect to the instance for set up and deployment. In a production setup, limit the IPs from which SSH is allowed.

Click Launch. On the next screen, click View All Instances.

It will take a few minutes for the instance to spin up.

Configure EC2 Instance

In this section, we'll install Docker on the instance, add an Elastic IP, and configure an IAM role.

Install Docker

Navigate back to the EC2 console, select the newly created instance, and grab the public IP address:

EC2 Public IP

Connect to your EC2 instance using the .pem key that we downloaded in the "AWS EC2" step.

$ ssh -i /path/to/your/djangoletsencrypt.pem ubuntu@public-ip-or-domain-of-ec2-instance

Your .pem was probably downloaded into path like ~/Downloads/your-key-pair-name.pem. If you're not sure where to store it, move it into the "~/.ssh" directory. You may have to also change the permissions -- e.g., chmod 400 -i /path/to/your/your-key-pair-name.pem.

Start by installing the latest version of Docker and version 1.29.2 of Docker Compose:

$ sudo apt update
$ sudo apt install apt-transport-https ca-certificates curl software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
$ sudo apt update
$ sudo apt install docker-ce
$ sudo usermod -aG docker ${USER}
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

$ docker -v
Docker version 20.10.8, build 3967b7d

$ docker-compose -v
docker-compose version 1.29.2, build 5becea4c

Install AWS CLI

First, install unzip:

$ sudo apt install unzip

Download AWS CLI ZIP:

$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

Unzip its content:

$ unzip awscliv2.zip

Install AWS CLI:

$ sudo ./aws/install

Verify installation:

$ aws --version

Elastic IP

By default, instances receive new public IP address every time they start and re-start.

Elastic IP allows you to allocate static IPs for your EC2 instances, so the IP stays the same all the time and can be re-associated between instances. It's recommended to use one for your production setup.

Navigate to Elastic IPs and click Allocate Elastic IP address:

Elastic IP

Then, click Allocate:

Elastic IP Allocate

Select the newly created elastic IP address, click the Actions dropdown -> Associate this Elastic IP address:

Elastic IP Associate

Select your instance and click Associate:

Elastic IP Select Instance

IAM Role

We'll Docker pull images from AWS ECR to our EC2 instance during deployment. Since we won't be allowing public access to the Docker image on ECR, you'll need to create an IAM role with permissions to pull Docker images from ECR and attach it to your EC2 instance.

Navigate to the IAM console.

Click Roles in the left sidebar and then Create role:

Read full article→

Back to Top