Skip to content
fg
cd ../blog

updated 4 min read

How to Deploy a Flask Application Using NGINX on AWS ECS — Part 1

Deploying a Flask application using NGINX on AWS ECS might seem too complex at first, but this article is the ultimate guide to help you through all the steps.

Let’s start by defining some fundamental concepts:

Flask is a popular web framework for building web applications in Python. It is a lightweight framework that provides valuable tools and features for building web applications, such as routing, request handling, and template rendering.

NGINX is a web server often used as a reverse proxy, load balancer, and HTTP cache.

Amazon Elastic Container Service (ECS) is a fully-managed container orchestration service provided by Amazon Web Services (AWS). It allows developers to deploy, manage, and scale containerized applications on AWS quickly. With ECS, developers can run and manage Docker containers on a cluster of Amazon EC2 instances, making it easy to build, ship, and run distributed applications.

Our goal:

AWS ECS architecture for Flask and NGINX containers

The image above shows the AWS Architecture diagram where we have both containers NGINX + FLASK defined within the Task Definition running as a Service inside an AWS Fargate Cluster. Our application will be running inside two private subnets without direct access from the Internet; in this case, it will be our Application Load Balancer redirecting HTTP traffic to our application.

The Elastic Network Interface will allow our service to communicate with other resources in the AWS cloud, such as AWS ECR, over a virtual private network (VPN) or the internet.

To understand more about these concepts, please read the following blog post: https://start.jcolemorrison.com/aws-vpc-core-concepts-analogy-guide/

Steps:

  1. Create the Flask application
  2. Create the Docker image for the Flask application
  3. Configure & Create the Docker image for NGINX

1. Create the Flask application

Initialize the project with the following commands in your terminal:

mkdir project
mkdir application
cd application
python3 -m venv venv
source venv/bin/activate

Install Flask by running the following:

pip install flask

Create a subfolder in the application folder and name it app — , and another file in the app folder, named __init__.py :

mkdir app
cd app
touch __init__.py

Paste the following code inside the __init__.py file:

from flask import Flask

app = Flask(__name__)

from app import routes

Create a new file called routes.py in the app folder, and paste the following code in the routes.py file:

from app import app

@app.route('/')
@app.route('/index')
def index():
    return "Hello from my AWS ECS Container"

Now back to the application folder, create a file named start.py with the following code inside:

from app import app

Let’s install Gunicorn:

pip install gunicorn

And to complete this step, create the requirements.txt file by running the following command inside the application folder.

pip freeze > requirements.txt

Your folder structure should look like this:

project/
  application/
    venv/
    app/
      __init__.py
      routes.py
    start.py
    requirements.txt

2. Create the Docker image for the Flask application

Create a file named Dockerfile in the application folder with the following code:

FROM python:slim

RUN useradd project

WORKDIR /home/project

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY app app
COPY start.py ./

ENV FLASK_APP start.py

RUN chown -R project:project ./
USER project

EXPOSE 5000

CMD [ "gunicorn", "-b", ":5000", "--access-logfile", "-", "start:app"]

Now let’s build the image by running the following:

docker build -t project:latest .

Run a test to check if it is working correctly by starting the container, executing the following command, and then accessing it using your browser http://0.0.0.0:5000 :

docker run -d -p 5000:5000 --name project project

By now, you should be seeing this:

Output on the browser saying “Hello from my AWS ECS Container”

3. Configure & Create the Docker image for NGINX

Create a subfolder called nginx in the project folder and then inside create a file called nginx.conf:

cd project
mkdir nginx
touch nginx.conf

Paste the following code inside the nginx.conf file:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
   worker_connections  1024;
}

http {
   include       /etc/nginx/mime.types;
   default_type  application/octet-stream;

   log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';

   access_log  /var/log/nginx/access.log  main;

   sendfile        on;

   keepalive_timeout  65;

   server {

    listen 80;

    location / {
            proxy_pass         http://127.0.0.1:5000;
            proxy_redirect     off;
            proxy_set_header   Host $host:$server_port;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
 }
  }
}

Note: Between the server brackets, we have the location block where we are redirecting requests coming to / directly to our application on http://127.0.0.1:5000

Create a file named Dockerfile in the nginx folder with the following code:

FROM nginx:stable
COPY ./nginx.conf /etc/nginx/nginx.conf

Now let’s build the image by running the following:

docker build -t nginx:latest .

In Part 2, we will push our built images to AWS ECR and create our VPC network with the necessary components.

Stay tuned!

You can find this code also on my Github: https://github.com/filipegalo/flask-nginx/

And if you enjoy my content or if you have any questions, feel free to connect with me on X: @RoosterOps