Building a 2-Tier Application with Docker Compose (Flask + MySQL) — Step-by-Step Guide

Introduction
After successfully deploying a Flask app using Docker, I wanted to go one step further.
In real-world applications, we don’t just run a single container — we connect multiple services.
So in this project, I built a 2-tier application:
Flask (Backend)
MySQL (Database)
And honestly… this is where things got interesting.
Containers didn’t connect, services crashed, and debugging became the main learning.
In this blog, I’ll walk you through everything step-by-step — including real issues and fixes.
🎯 What You Will Learn
What is a 2-tier architecture
How to connect multiple containers
How Docker Compose works
How to use volumes for persistence
How to debug container communication issues
🏗️ Architecture Overview
User → Flask Container → MySQL Container
👉 Flask handles requests 👉 MySQL stores data
⚙️ Prerequisites
Docker installed
Basic Flask knowledge
Linux terminal basics
🚀 STEP-BY-STEP IMPLEMENTATION
🔵 Step 1: Project Structure
app.py
requirements.txt
Dockerfile
docker-compose.yml
🔵 Step 2: Flask App Code
Basic Flask app connecting to MySQL.
👉 Important part:
app.config['MYSQL_HOST'] = 'mysql'
⚠️ NOT localhost
🔵 Step 3: Create Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
🔵 Step 4: Create docker-compose.yml
services:
mysql:
image: mysql:5.7
environment:
MYSQL_DATABASE: devops
MYSQL_ROOT_PASSWORD: root
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
flask:
build: .
ports:
- "5000:5000"
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_DB: devops
depends_on:
- mysql
volumes:
mysql-data:
🔵 Step 5: Run Application
docker compose up -d
🔵 Step 6: Access Application
http://your-ip:5000
🔥 REAL PROBLEMS I FACED
(MOST IMPORTANT)
❌ Problem 1: Flask Couldn’t Connect to MySQL
Error:
Can't connect to server on 'mysql'
Cause:
- MySQL not ready yet
Fix:
- Add retry logic OR restart policy
❌ Problem 2: Using localhost
Wrong:
localhost ❌
Correct:
mysql (service name) ✅
❌ Problem 3: Data Loss
Cause:
- No volume
Fix:
volumes:
- mysql-data:/var/lib/mysql
❌ Problem 4: YAML Errors
Cause:
Wrong indentation
Wrong keys
Fix:
- Proper formatting
❌ Problem 5: Container Restart Loop
Cause:
- Dependency issue
Fix:
restart policy
proper service handling
🧠 KEY LEARNINGS
Containers are isolated but connected via network
Docker Compose simplifies multi-container apps
Volumes are critical for databases
Debugging is the most important skill
🚀 FINAL OUTPUT
Flask app running
MySQL connected
Data stored successfully
Multi-container system working
🚀 WHAT’S NEXT
Add Nginx (reverse proxy)
Deploy using ECS
Move to Kubernetes
💡 FINAL THOUGHTS
This project taught me:
“Running multiple services is not just about starting containers — it’s about making them communicate properly.”
If you’re learning DevOps: 👉 Start small 👉 Then build systems 👉 Then break and debug
🙌 Connect With Me
More DevOps projects coming soon 🚀

