Description: Build a simple Python + Flask + MySQL microservice, containerize it with Docker, and demonstrate container monitoring and log management
Objective
Learn to:
- Build a simple Python web app (Flask)
- Containerize it using Docker
- Connect it with a MySQL database container
- Monitor logs, running containers, and troubleshoot errors
π§° 1. Prerequisites
Ensure the following are installed on your Ubuntu system:
docker -v
docker-compose -v
python3 -V
If docker-compose is missing, install:
sudo apt install docker-compose -y
π 2. Project Folder Structure
python-docker-demo/
β
βββ app/
β βββ app.py
β βββ config.py
β βββ requirements.txt
β βββ Dockerfile
β
βββ docker-compose.yml
βββ README.md
π 3. Create Application Files
a. app.py
from flask import Flask, jsonify
import mysql.connector
import os
app = Flask(__name__)
db_config = {
"host": os.getenv("DB_HOST", "mysql"),
"user": os.getenv("DB_USER", "root"),
"password": os.getenv("DB_PASS", "password"),
"database": os.getenv("DB_NAME", "quotesdb")
}
@app.route('/')
def home():
return jsonify({"message": "Welcome to Python + Docker Demo!"})
@app.route('/quotes')
def get_quotes():
try:
conn = mysql.connector.connect(**db_config)
cursor = conn.cursor()
cursor.execute("SELECT text, author FROM quotes")
result = cursor.fetchall()
cursor.close()
conn.close()
return jsonify(result)
except Exception as e:
return jsonify({"error": str(e)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
b. config.py
DB_HOST = "mysql"
DB_USER = "root"
DB_PASS = "password"
DB_NAME = "quotesdb"
c. requirements.txt
flask
mysql-connector-python
π³ 4. Create Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
π§© 5. Create docker-compose.yml
This will bring up both the Python app and MySQL containers together.
version: '3.8'
services:
app:
build: ./app
container_name: python_app
ports:
- "5000:5000"
environment:
- DB_HOST=mysql
- DB_USER=root
- DB_PASS=password
- DB_NAME=quotesdb
depends_on:
- mysql
restart: always
mysql:
image: mysql:5.7
container_name: mysql_db
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: quotesdb
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
βοΈ 6. Initialize the Database
Once containers are up, create the table and insert sample data.
docker exec -it mysql_db mysql -uroot -ppassword -e "CREATE DATABASE IF NOT EXISTS quotesdb;"
docker exec -it mysql_db mysql -uroot -ppassword -e "USE quotesdb; CREATE TABLE quotes (id INT AUTO_INCREMENT PRIMARY KEY, text VARCHAR(255), author VARCHAR(100));"
docker exec -it mysql_db mysql -uroot -ppassword -e "USE quotesdb; INSERT INTO quotes (text, author) VALUES ('Life is what happens when youβre busy making other plans.', 'John Lennon');"
βΆοΈ 7. Build and Run
docker-compose up --build
Access app:
π http://localhost:5000
π http://localhost:5000/quotes
π§Ύ 8. Log Monitoring and Container Management
| Task | Command | Description |
|---|---|---|
| List running containers | docker ps | Shows container IDs and names |
| View logs | docker logs python_app | View app logs |
| Follow logs live | docker logs -f python_app | Monitor real-time logs |
| Enter container shell | docker exec -it python_app /bin/bash | Access running container |
| Restart container | docker restart python_app | Restart service |
| View resource usage | docker stats | CPU, memory, network stats |
| Remove stopped containers | docker container prune | Clean up |
| Stop all containers | docker stop $(docker ps -q) | Gracefully stop everything |
π¨ 9. Troubleshooting Common Issues
| Issue | Cause | Fix |
|---|---|---|
| Flask app not accessible | Port not exposed | Check Dockerfile & Compose port mapping |
| Database connection failed | Wrong env vars or DB not ready | Add depends_on and retry logic |
| CrashLoop or container exits | Syntax / runtime error | Run docker logs python_app |
| MySQL permission denied | Wrong credentials | Check env vars & MySQL logs |
π 10. Clean Up
docker-compose down
docker system prune -a
