Skip to main content

Command Palette

Search for a command to run...

🐳 Docker - Day 11 : Deploying a Two-Tier Flask Application on AWS EC2

Containerizing and Deploying a Flask App with Database on EC2

Published
4 min read
🐳 Docker - Day 11 : Deploying a Two-Tier Flask Application on AWS EC2
A

Cloud & DevOps enthusiast learning in public ☁️⚙️ Documenting my journey through systems, automation, and real-world engineering problems. Focused on fundamentals, practical learning, and continuous growth.

Docker + Docker Compose (Production-Style Walkthrough)

In this blog, we deploy a two-tier Todo application (Flask + MySQL) on an AWS EC2 instance using Docker and Docker Compose.

This day focuses on:

  • EC2 setup

  • Docker & Docker Compose installation

  • Building and pushing Docker images

  • Running a two-tier app using Docker Compose


1️⃣ Architecture Overview

Two-Tier Application Architecture

User
  ↓
Flask Application (Docker Container)
  ↓
MySQL Database (Docker Container)
  • App Tier → Flask (Python)

  • DB Tier → MySQL

  • Orchestration → Docker Compose

  • Hosting → AWS EC2


2️⃣ AWS EC2 Setup

🔹 Create EC2 Instance

  • AMI: Ubuntu 22.04

  • Instance type: t2.micro / t3.micro

  • Key pair: Create or use existing

🔹 Security Group Rules

Allow inbound traffic on:

PortPurpose
22SSH
80HTTP
443HTTPS
5000Flask App

📌 Outbound: Allow all


3️⃣ Connect to EC2 & Update System

ssh -i key.pem ubuntu@<EC2-PUBLIC-IP>
sudo apt update && sudo apt upgrade -y

4️⃣ Install Docker

sudo apt install docker.io -y
# Check
sudo systemctl status docker

# If needed
sudo systemctl start docker
sudo systemctl enable docker

🔹 Add User to Docker Group

# Create the docker group.
sudo groupadd docker

# Add your user to the docker group.
sudo usermod -aG docker $USER

# Activate the changes to groups
newgrp docker

Verify:

docker --version


5️⃣ Install Docker Compose

sudo apt install docker-compose -y

Verify:

docker-compose --version


6️⃣ Clone the Application Repository

git clone https://github.com/arvindhvetri/FlowList-DevOps-Deployment.git
cd FlowList-DevOps-Deployment


7️⃣ Dockerfile – Flask Application Image

📄 Dockerfile

# Use a lightweight Python base image to keep the final size small
FROM python:3.9-slim

# Set the working directory inside the container for all subsequent commands
WORKDIR /app

# Install system dependencies required for compiling mysqlclient
# We clean up apt logs afterward to reduce the image layer size
RUN apt-get update \
    && apt-get install -y gcc default-libmysqlclient-dev pkg-config \
    && rm -rf /var/lib/apt/lists/*

# Copy only requirements first to leverage Docker's build cache
COPY requirements.txt .

# Install Python dependencies and the MySQL driver for Python
RUN pip install --no-cache-dir -r requirements.txt mysqlclient

# Copy the rest of the application source code into the container
COPY . .

# Document that the container listens on port 8000
EXPOSE 8000

# Specify the default command to run your Flask or Django application
CMD ["python", "app.py"]

🔍 Dockerfile Explanation

🔹 Base Image

  • python:3.9-slim

  • Lightweight and production-friendly

🔹 System Dependencies

  • gcc, libmysqlclient-dev

  • Required for building mysqlclient Python package

🔹 Dependency Installation

  • requirements.txt copied first for caching

  • Reduces rebuild time

🔹 Application Code

  • Copied after dependencies

  • Follows Docker layer optimization best practice

🔹 CMD

  • Starts Flask app using python app.py

📌 This image is generic, reusable, and production-aligned.


8️⃣ Build Docker Image

docker build -t arvindh01/todolist-app:latest .

Verify:

docker images


9️⃣ Docker Login & Push Image to Docker Hub

🔹 Login

docker login -u your_username

Enter:

  • Docker Hub username

  • Password / token

🔹 Push Image

docker push arvindh01/todolist-app:latest

📌 Image is now available globally and reusable in Compose.


🔟 Docker Compose – Two-Tier Application

📄 docker-compose.yml

version: "3.8"

services:
  mysql:
    image: mysql:5.7
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: admin
      MYSQL_DATABASE: tododb
    volumes:
      - ./mysql-data:/var/lib/mysql
      - ./table.sql:/docker-entrypoint-initdb.d/table.sql
    networks:
      - twotier
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-padmin"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 60s

  flask-app:
    image: arvindh01/todolist-app:latest # Dockerhub Image : 2tier-todoapp
    container_name: todoapp
    ports:
      - "5000:8000"
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: admin
      MYSQL_DB: tododb
    depends_on:
      mysql:
        condition: service_healthy
    networks:
      - twotier
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

networks:
  twotier:
    driver: bridge

1️⃣1️⃣ Docker Compose Explanation

🔹 MySQL Service

  • Uses official MySQL 5.7 image

  • Initializes DB + tables automatically

  • Data persisted using volumes

  • Health check ensures DB readiness

🔹 Flask App Service

  • Pulls image from Docker Hub

  • Uses service name mysql as DB host

  • Exposed via port 5000

  • Starts only after DB becomes healthy

🔹 Network

  • User-defined bridge network (twotier)

  • Enables DNS-based service discovery


1️⃣2️⃣ Start the Application

docker-compose up -d

Check:

docker-compose ps

Logs:

docker-compose logs -f

1️⃣3️⃣ Access the Application

Open browser:

http://<EC2-PUBLIC-IP>:5000

🎉 Your two-tier Flask + MySQL app is live on AWS.

Docker Simplified: A Beginner's Guide

Part 10 of 10

A beginner-friendly Docker series covering core concepts, architecture, hands-on examples, Dockerfiles, images, containers, and real-world usage — explained in simple terms.

Start from the beginning

🐳 Containers - Day 1 : Introduction

What Are Containers and Why Docker Uses Them