Are you looking to deploy a Django app on Elastic Container Service at scale? This comprehensive guide is designed to help you do just that. With step-by-step instructions, you’ll learn how to create an Elastic Container Registry, set up an Elastic Load Balancer, create an Elastic Container Service, and configure auto-scaling.

In addition, this guide covers important security considerations, such as updating security groups and ensuring a secure AWS environment.

Let’s start without wasting time.

Index

Part 1: Coding the XKCD Django App

Coding the XKCD Django App

  1. Creating and activating a virtual environment
  2. Installing Django
  3. Creating database models
  4. Adding models to the Django admin page
  5. Creating the homepage view
  6. Adding homepage view to URLs
  7. Creating homepage.html
  8. Creating requirements.txt file
  9. Dockerizing our Django App
    1. Testing the Docker Image

Part 2: AWS: Configuring RDS, Parameter Store, ElastiCache

Configuring AWS

  1. AWS RDS – Relational Database Service
    1. Configuring RDS Security Group
    2. Creating a Postgresql Database on RDS
    3. Updating Django settings to use the PostgreSQL Database Backend
      1. Install the PostgreSQL library
      2. Update the settings.py
  2. AWS Systems Manager Parameter Store
    1. Adding our secrets to Parameter Store
    2. Configuring Django App to use AWS Parameter Store
      1. Install AWS SDK for Python: boto3
      2. Update the settings.py file
    3. Migrating Django models to RDS instance
    4. Build & run the docker image with the aws credentials
    5. Creating Parameter Store IAM Role
    6. Creating a super user
  3. ElastiCache Redis
    1. Creating the Security Group: XKCDAppElastiCacheSecurityGroup
    2. Creating the ElastiCache Redis Instance
    3. Adding ElastiCache endpoint to Parameter Store
    4. Installing django-redis package
    5. Updating Django settings to use Redis as Session Storage

Part 3: AWS: Deploying XKCD App to Elastic Container Service

  1. Elastic Container Registry
    1. Uploading XKCD Apps Docker Image to ECR
  2. Elastic Load Balancing
    1. ELB Security Group Creation
    2. ELB Creation
      1. Step 1: Configure Load Balancer
      2. Step 2: Security Settings
      3. Step 3: Security Groups
      4. Step 4: Routing: Target Group Creation
      5. Step 5: Registering Targets to Target Group
      6. Step 6: Review
      7. Step 7: Forward traffic from port 80 to port 8000
  3. Elastic Container Service
    1. Creating an ECS Task Execution Role: XKCDAppECSTaskExecutionRole
    2. Creating ECS security group: XKCDAppECSSecurityGroup
    3. Creating Task Definition: XKCDAppTaskDefinition
      1. Adding a container to XKCDAppTaskDefinition
    4. Creating Cluster Service
      1. Step 1: Configure Service
      2. Step 2: Configure Network
      3. Step 3: Set Auto Scaling
      4. Step 4: Review
    5. Load Testing our App with Hey
    6. Creating Auto Scaling for XKCDAppClusterService
      1. Testing the Auto Scaling Policy
  4. Updating Security Groups
    1. Updating XKCDAppElasticLoadBalancerSecurityGroup
    2. Updating XKCDAppECSSecurityGroup
    3. Updating XKCDAppElastiCacheSecurityGroup
    4. Updating XKCDAppRDSSecurityGroup

1. Elastic Container Registry

Go to Repositories under Elastic Container Registry and click on the Create Repository button. Give your ECR repository a name and click “create”.

Elastic Container Registry

Elastic Container Registry Creation

1.1 Uploading XKCD Apps Docker Image to ECR

Go to the detail page of your repository and click View Push Commands on the upper right. This will give you loginbuildtag and push commands specific to your repository.

# get credentials to ECR Repo
aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin 12345678912.dkr.ecr.eu-west-2.amazonaws.com

#build your image
docker build -t xckdapp .

# tag it as the latest
docker tag xckdapp:latest 12345678912.dkr.ecr.eu-west-2.amazonaws.com/xckdapp:latest

# push to ECR
docker push 12345678912.dkr.ecr.eu-west-2.amazonaws.com/xckdapp:latest

2. Elastic Load Balancing

We are going to access our Elastic Container Service container instances through an AWS Elastic Load Balancer. We are going to create the ELB first in order to add it to Elastic Container Service upon creation.

2.1 ELB Security Group Creation

Go to Security Groups under VPC and create one.

ELB Security Group Creation

ELB Security Group Creation

 

Setting Option
Name XKCDAppElasticLoadBalancerSecurityGroup
Description XKCDApps Elastic Load Balancer Security Group.
VPC Select your VPC, or use the default one.
Inbound Rules Type: HTTP, Source: Anywhere
Inbound Rules Type: HTTPS Source: Anywhere
Inbound Rules Type: CustomTCP, Port Range: 8000, Source: Anywhere
Outbound Rules Type: All Trafic, Destination: Anywhere

 

2.2 ELB Creation

Go to Load Balancers under EC2 and click on Create Load Balancer button and select Application Load Balancer.

2.2.1 – Step 1: Configure Load Balancer

Configure Load Balancer

 

ELB Creation: Configuring the Load Balancer

For Availability Zones, you should remember your AZ choices, as you will need to use the same configuration for Elastic Container Service creation.

Configure Load Balancer

ELB Creation: Configuring availability zones

 

Setting Option
Load Balancer Type Application Load Balancer
Name XKCDAppELB
Scheme internet-facing
IP address type ipv4
Listeners HTTP: 80
Listeners HTTP: 8000
Availability Zones 2a, 2b, 2c

 

2.2.2 – Step 2: Security Settings

 

Security Settings

ELB Creation: Target Group Creation

We are not going to use HTTPS for this demo, feel free to skip this step.

2.2.3 – Step 3: Security Groups

Security Groups

ELB Creation: Security Group Selection

2.2.4 – Step 4: Routing: Target Group Creation

Target Group Creation

ELB Creation: Target Group Creation

 

Setting Option
Target Group New target group
Name XKCDAppClusterServiceTargetGroup
Target Type IP
Protocol HTTP
Port 8000
Protocol version HTTP1
Health Checks: Protocol HTTP
Health Checks: Path /

 

2.2.5 – Step 5: Registering Targets to Target Group

Feel free to skip this step, ECS will go to manage target groups.

2.2.6 – Step 6: Review

Click on the create button. And when you go back to the Load Balancers console, you should see something like this.

Name DNS name state
XKCDAppELB XKCDAppELB-123456789.eu-west-2.elb.amazonaws.com provisioning

We will be using the DNS name to connect to our ECS instances, take note of it.

2.2.7 – Step 7: Forward traffic from port 80 to port 8000

Go to Listeners tab on XKCDAppELB’s detail view under Load balancers. On listener HTTP: 80 click on view/edit rules.

Forward traffic from port 80 to port 8000

ELB Port Forwarding: Target Group Creation

Add a rule to forward HTTP:80 traffic to HTTP:8000.

Setting Option
Path *
Redirect to HTTP 8000
HTTP Code 301 – Permanently Moved

 

Target Group creation

Port Forwarding: Adding a Rule Group Creation

3. Elastic Container Service

3.1 Creating an ECS Task Execution Role: XKCDAppECSTaskExecutionRole

Go to Role under IAM and click on the create role button. Attach policies below:

  1. AmazonECSTaskExecutionRolePolicy (aws managed)
  2. SystemManagerParameterStoreFullAccess (custom)

Elastic Container Service

ECS Task Role Creation

 

3.2 Creating ECS security group: XKCDAppECSSecurityGroup

Creating ECS security group

Creating ECS security group: XKCDAppECSSecurityGroup

 

Setting Option
Name XKCDAppECSSecurityGroup
Description XKCD Apps security group, allows container ports
VPC Select your VPC, or use the default one.
Inbound Rules Type: CustomTCP, Port Range: 80, Source: Anywhere
Inbound Rules Type: CustomTCP, Port Range: 8000, Source: Anywhere
Outbound Rules Type: All Trafic, Destination: Anywhere

 

3.3 Creating Task Definition: XKCDAppTaskDefinition

Go to Task Definitions under Elastic Container Service and create a task definition.

Creating Task Definition

Creating Task Definition:

Configure task and container definitions

 

Setting Option
Launch Type Fargate
Name XKCDAppTaskDefinition
Task Role XKCDAppECSTaskExecutionRole
Network mode awsvpc
Task Execution Role ecsTaskExecutionRole
Task Memory 2 GiB
Task CPU 1vCPU

 

3.3.1 Adding a container to XKCDAppTaskDefinition

Click on Add container button under the section Container Definitions

Adding a container to XKCDAppTaskDefinition

Remember to append :latest tag to your Elastic Container Registry URI.

 

Setting Option
Container name XKCDAppContainer
Image 12345678912.dkr.ecr.eu-west-2.amazonaws.com/xkcdapp:latest
Port Mappings 8000 TCP
Port Mappings 80 TCP

 

3.4 Creating Cluster Service

Click on the default cluster on Clusters page under Elastic Container Service.

Creating Cluster Service

AWS ECS default cluster

Click on Create button under Services.

3.4.1 – Step 1: Configure Service

Configure Service

 

Setting Option
Launch Type Fargate
Task Definition XKCDAppTaskDefinition
Task Revision 1(latest)
Platform Version Latest
Cluster default
Service name XKCDAppClusterService
Service Type Replica
Number of tasks 1
Min healthy percent 100
Max percent 200

 

3.4.2 – Step 2: Configure Network

VPC & Security Group

VPC & Security Group

 

Setting Option
Cluster VPC default
Subnets 2a, 2b, 2c
Security Group Select existing: XKCDAppECSSecurityGroup
Auto-assign public IP ENABLED

 

Load Balancing

Load Balancing

 

Setting Option
Load Balancer Type Application Load Balancer
Load Balancer Name XKCDAppELB

 

Container to load balance

Container to load balance

 

Setting Option
Production Listener Port 80:HTTP
Production Listener Protocol HTTP
Target group name Select existing: XKCDAppClusterServiceTargetGroup
Target group protocol HTTP
Target type IP
Path Pattern /
Evaluation Order default
Health check path /

 

3.4.3 – Step 3: Set Auto Scaling

We will configure auto-scaling later. Skip this step for now.

3.4.4 – Step 4: Review

Make sure your changes are correct and click on Create Service button.

Go to Tasks tab under Service: XKCDAppClusterService, and wait for your task’s status to be RUNNING.

Now you can go to your Elastic Load Balancer’s DNS name which is something like this: http://xkcdappelb-12346578.eu-west-2.elb.amazonaws.com:8000/

If you haven’t done the ELB port forwarding remember to append the port :8000 to DNS name.

3.5 Load Testing our App with Hey

Hey is an open-sourced load testing tool. We will be using it to test how well a single container of the XKCD App does under load. And with the information we get out of load-testing, we can decide on a good Auto Scaling Policy.

Let’s run hey with 100 requests, 1 concurrent request at a time.

❯ hey -n 100 -c 1 http://xkcdappelb-123456789.eu-west-2.elb.amazonaws.com:8000/

Summary:
  Total:	64.8392 secs
  Slowest:	1.6920 secs
  Fastest:	0.1304 secs
  Average:	0.6484 secs
  Requests/sec:	1.5423

  Total data:	109851 bytes
  Size/request:	1098 bytes

Response time histogram:
  0.130 [1]	|■
  0.287 [6]	|■■■■■■
  0.443 [22]	|■■■■■■■■■■■■■■■■■■■■
  0.599 [7]	|■■■■■■■
  0.755 [43]	|■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.911 [1]	|■
  1.067 [16]	|■■■■■■■■■■■■■■■
  1.224 [2]	|■■
  1.380 [0]	|
  1.536 [1]	|■
  1.692 [1]	|■


Latency distribution:
  10% in 0.3377 secs
  25% in 0.3638 secs
  50% in 0.6604 secs
  75% in 0.7351 secs
  90% in 1.0325 secs
  95% in 1.0596 secs
  99% in 1.6920 secs

Details (average, fastest, slowest):
  DNS+dialup:	0.0065 secs, 0.1304 secs, 1.6920 secs
  DNS-lookup:	0.0058 secs, 0.0000 secs, 0.5765 secs
  req write:	0.0000 secs, 0.0000 secs, 0.0001 secs
  resp wait:	0.6418 secs, 0.1302 secs, 1.5321 secs
  resp read:	0.0001 secs, 0.0000 secs, 0.0003 secs

Status code distribution:
  [200]	100 responses

In almost a minute, our application responded to 100 requests and it responded in an average of 0.64 seconds. You can try to experiment with hey, change the request count, update your Task Definition’s RAM or vCPU, etc.

That’s the ideal situation for XKCD App, so we will configure the Auto Scaling condition to be 100 requests per minute per instance.

3.6 Creating Auto Scaling for XKCDAppClusterService

Go to XKCDAppClusterService under default cluster and click update.

Creating Auto Scaling for XKCDAppClusterService

Configuring AWS ECS Auto Scaling

Configuring AWS ECS Auto Scaling

Set up a reasonable Auto Scaling Policy.

Configuring AWS ECS Auto Scaling Policy

3.6.1 Testing the Auto Scaling Policy

Normally, XKCDAppClusterService’s desired count of instances is 1.

Testing the Auto Scaling Policy

But when I load-test it again with Hey,

❯ hey -n 400 -c 10 http://xkcdappelb-123456798.eu-west-2.elb.amazonaws.com:8000/

I could see that my instance count increased after cool-down time.

Testing the Auto Scaling Policy

4. Updating Security Groups

Our XKCD App runs on the security group configuration of the below diagram.

Updating Security Groups

If we follow the access through the security groups, we can come up with an inbound/outbound access table:

inbound outbound
Public Internet XKCDAppElasticLoadBalancerSecurityGroup
XKCDAppElasticLoadBalancerSecurityGroup XKCDAppECSSecurityGroup
XKCDAppECSSecurityGroup XKCDAppElastiCacheSecurityGroup
XKCDAppECSSecurityGroup XKCDAppRDSSecurityGroup

Let’s update our security groups. Go to Security Groups under VPC.

 

4.1 Updating XKCDAppElasticLoadBalancerSecurityGroup

Select XKCDAppElasticLoadBalancerSecurityGroup and edit the rules.

Rule Type Type Destination Type Destination
Inbound HTTP:80 Anywhere
Inbound Custom TCP: 8000 Custom Anywhere
Outbound All Traffic Custom XKCDAppECSSecurityGroup

 

4.2 Updating XKCDAppECSSecurityGroup

Select XKCDAppECSSecurityGroup and edit the rules.

Rule Type Type Destination Type Destination
Inbound HTTP:80 Custom XKCDAppElasticLoadBalancerSecurityGroup
Inbound Custom TCP: 8000 Custom XKCDAppElasticLoadBalancerSecurityGroup
Outbound All Traffic Anywhere
Outbound Custom TCP: 6379 Custom XKCDAppElastiCacheSecurityGroup
Outbound Custom TCP: 5432 Custom XKCDAppRDSSecurityGroup

 

4.3 Updating XKCDAppElastiCacheSecurityGroup

Select XKCDAppElastiCacheSecurityGroup and edit the rules.

Rule Type Type Destination Type Destination
Inbound TCP: 6379 Custom XKCDAppECSSecurityGroup

 

4.4 Updating XKCDAppRDSSecurityGroup

Select XKCDAppRDSSecurityGroup and edit the rules.

Rule Type Type Destination Type Destination
Inbound TCP: 5432 Custom XKCDAppECSSecurityGroup

Conclusion

If you’ve followed this blog post to the end, you should have a secure AWS environment where a Django app is served on Elastic Container Service at scale. We created multiple services for our application’s needs and configured their network settings to accept traffic from where they’re supposed to. And also, our application secrets are located securely in the AWS Parameter Store.

If you would like to tighten the security of your AWS environment, please consider configuring your VPC securely. You can read more about secure VPC design in our previous blog post Secure AWS VPC Design and Configuration Guide.

Check out our DevOps services to stay secure!