How I Deployed a 2-Tier Flask App with MySQL Database


Introduction
Recently, I worked on deploying a 2-Tier Flask application with a MySQL database. The goal was to containerize both services using Docker and manage them with Docker Compose for easy deployment.
I started by creating a Dockerfile for the Flask application. I used a Python base image, created a working directory, and copied the application code from the src
folder into it. Then, I installed all the required dependencies and libraries. Finally, I added a CMD
instruction to run the app with python
app.py
.
After that, I created a docker-compose.yml file to manage both services—Flask and MySQL. This helped me avoid writing long docker commands manually and made it easier to define configurations in a key-value format.
Docker Compose Setup
In the docker-compose.yml
file, I defined two services:
✅ MySQL Container
Gave it a custom container name
Built the image
Set necessary environment variables (like root username/password)
Mounted volumes to persist data even if the container was removed
Added a healthcheck to verify if the MySQL container was alive by running
mysqladmin ping
with retries, intervals, and a startup periodExposed the host port
3306
mapped to container port3306
✅ Flask Container
Set the container name and built the image
Tagged and pushed the image to Docker Hub, then pulled it back for deployment
Exposed the host port
5000
mapped to container port5000
Set required environment variables
Added a depends_on condition for MySQL to ensure it only starts after the database is healthy
Added a healthcheck to hit
localhost:5000/health
and verify the response is200 OK
Set restart policy to
always
I also created a bridge network so that both containers could communicate internally. This allowed the Flask application to connect directly to the MySQL database.
Finally, I ran docker compose up
to deploy the application.
The Challenge
Initially, the deployment didn’t work as expected. The Flask container didn’t respond on port 5000
when accessed publicly.
After some debugging, I realized the issue was with the AWS EC2 security group rules. I forgot to allow inbound traffic on port 5000
, so the instance was blocking external requests.
The Fix
I went to my AWS EC2 instance Networking → Security Groups → Edit Inbound Rules and added a new rule:
Custom TCP Rule for port
5000
Source: Anywhere (0.0.0.0/0)
Once I updated the firewall rules, the application became accessible at:
http://public-ip:5000/health
And finally, the deployment was successful! ✅
Key Learnings
Always double-check security group rules when deploying apps on AWS EC2.
Docker healthchecks are very helpful to ensure services are running as expected.
Using Docker Compose makes multi-container deployments much easier and cleaner.
Tech Stack
AWS EC2 Instance
Docker
Docker Compose v2
Docker Hub Registry
Links
🔗 GitHub Repository: (https://github.com/jj6977/two-tier-flask-app)
Subscribe to my newsletter
Read articles from Junaid Javed directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
