Two-tier flask application with flask and mysql using docker-compose
Docker Compose is a powerful tool for defining and running multi-container Docker applications. It allows you to use a YAML file to configure your application's services, networks, and volumes, making it easy to define the relationships between them and spin up your entire application stack with a single command.
With Docker Compose, you can:
Define Services: You can define each component of your application (such as web server, database, cache, etc.) as a separate service in your
docker-compose.yml
file. Each service can have its own configuration, including Docker image, environment variables, ports, volumes, and more.Manage Dependencies: Docker Compose automatically handles the dependencies between services. For example, if your web server depends on a database, you can specify this relationship in the
docker-compose.yml
file, and Docker Compose will ensure that the database container is started before the web server container.Simplify Development Workflow: Docker Compose streamlines the development workflow by allowing you to define your entire application environment in a single configuration file. This makes it easy to spin up your development environment on a new machine or share it with other team members.
Scalability and Portability: Docker Compose configurations are portable and can be used across different environments, including development, testing, and production. You can easily scale your application by running multiple instances of the same service, and Docker Compose will handle load balancing and routing between them.
Integration with Docker CLI: Docker Compose integrates seamlessly with the Docker CLI, allowing you to use familiar commands like
docker-compose up
,docker-compose down
,docker-compose build
, anddocker-compose exec
to manage your application.
git hub link: https://github.com/Pardeep32/two-tier-flask-app.git
To create a two-tier application with the first tier (such as a web server) in container1 and the database tier in container2 using Docker Compose, you can follow these steps:
Step1 - Launch an ec2 instance and install docker on the instance by following commands:
# Update package information
sudo apt update
# Install Docker
sudo apt install docker.io
# Check your username (you can skip this if you know your username)
whoami
# Add your user to the 'docker' group
sudo usermod -aG docker $USER
# Verify that your user is added to the 'docker' group
sudo cat /etc/group
# Restart Docker
sudo systemctl restart docker
# Reboot the instance (optional, if needed)
sudo reboot
Make sure to replace $USER
with your actual username obtained from the whoami
command.
now, you should have Docker installed and configured on your EC2 instance, and your user should be part of the docker
group. You can reconnect to your instance to use Docker to run containers as needed.
Now, create a directory two-tier-app.
create a flask web application (backend code will be provided by devlopers) vim app.py
and write the following code.
import os
from flask import Flask, render_template, request, redirect, url_for
from flask_mysqldb import MySQL
app = Flask(__name__)
# Configure MySQL from environment variables
app.config['MYSQL_HOST'] = os.environ.get('MYSQL_HOST', 'localhost')
app.config['MYSQL_USER'] = os.environ.get('MYSQL_USER', 'default_user')
app.config['MYSQL_PASSWORD'] = os.environ.get('MYSQL_PASSWORD', 'default_password')
app.config['MYSQL_DB'] = os.environ.get('MYSQL_DB', 'default_db')
# Initialize MySQL
mysql = MySQL(app)
@app.route('/')
def hello():
cur = mysql.connection.cursor()
cur.execute('SELECT message FROM messages')
messages = cur.fetchall()
cur.close()
return render_template('index.html', messages=messages)
@app.route('/submit', methods=['POST'])
def submit():
new_message = request.form.get('new_message')
cur = mysql.connection.cursor()
cur.execute('INSERT INTO messages (message) VALUES (%s)', [new_message])
mysql.connection.commit()
cur.close()
return redirect(url_for('hello'))
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
This code is a Python script for a basic web application built using the Flask framework. The application allows users to view a list of messages and submit new messages. It also uses a MySQL database to store and retrieve messages.
Here's a breakdown of the code:
Import necessary libraries:
os
: Used for accessing environment variables.Flask
: A popular web framework for building web applications in Python.render_template
: Flask function for rendering HTML templates.request
: Flask object for handling HTTP requests.redirect
andurl_for
: Used for redirecting to different routes in the application.MySQL
: A Flask extension for working with MySQL databases.
Create a Flask application:
app = Flask(__name__)
: This line creates a Flask web application instance.
Configure MySQL:
- The code sets up the MySQL database connection using configuration parameters read from environment variables (or default values if the variables are not set). These parameters include the host, user, password, and database name.
Initialize the MySQL extension:
mysql = MySQL(app)
: This line initializes the Flask-MySQL extension using the Flask app instance, allowing you to interact with the MySQL database easily.
Define routes and views:
The code defines two routes:
'/'
(the root route): This route is associated with thehello()
function. It retrieves messages from the MySQL database and renders them on the 'index.html' template.'/submit'
: This route is associated with thesubmit()
function. It handles HTTP POST requests, inserting new messages into the database, and then redirects back to the root route.
The
hello()
function:This function fetches messages from the MySQL database using a cursor.
It uses SQL to select all messages from a table called 'messages'.
The retrieved messages are passed to the 'index.html' template as a variable called
messages
.
The
submit()
function:This function handles the submission of new messages.
It extracts the new message from the form submitted in the request.
It inserts the new message into the 'messages' table in the MySQL database using SQL.
After successfully adding the message, it commits the changes to the database and redirects the user back to the root route.
Run the application:
- The code block at the end of the script runs the Flask application on the host '0.0.0.0' (accessible from any IP address) and port 5000. The
debug=True
argument enables debug mode, which helps during development but should be turned off in production.
- The code block at the end of the script runs the Flask application on the host '0.0.0.0' (accessible from any IP address) and port 5000. The
This code creates a simple web application for displaying and submitting messages using Flask and MySQL. Make sure you have Flask and Flask-MySQLdb installed, and you have a MySQL database set up with the appropriate schema to use this code successfully.
For frontend, flask app has templates:
vim index.html
write the followng code in index.html (this is also provided by developers).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flask App</title>
<style>
body, h1, p, form, input {
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: #f4f4f4;
}
.container {
max-width: 800px;
margin: 50px auto;
padding: 20px;
background-color: #fff;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
border-radius: 5px;
transition: box-shadow 0.3s ease;
}
.container:hover {
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
}
h1 {
color: #007BFF;
margin-bottom: 20px;
border-bottom: 2px solid #f0f0f0;
padding-bottom: 10px;
}
p {
color: #666;
margin-bottom: 10px;
}
form {
display: flex;
flex-direction: column;
gap: 10px;
}
input[type="text"] {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
transition: border-color 0.3s ease;
}
input[type="text"]:hover, input[type="text"]:focus {
border-color: #007BFF;
}
input[type="submit"] {
padding: 10px 15px;
background-color: #007BFF;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease, transform 0.3s ease;
}
input[type="submit"]:hover {
background-color: #0056b3;
transform: translateY(-2px);
}
input[type="submit"]:active {
transform: translateY(0);
}
@media (max-width: 600px) {
.container {
margin: 20px 10px;
}
input[type="text"] {
font-size: 14px;
}
}
</style>
</head>
<body>
<div class="container">
<h1>Hello Dosto,
Let's make a 2 Tier Application with Flask and MYSQL!</h1>
{% for message in messages %}
<p>{{ message[0] }}</p>
{% endfor %}
<form action="/submit" method="post">
<input type="text" name="new_message" placeholder="Enter a new message">
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
make a file requirement.txt and add required librares in this application:flask,mysql and requests.
vim requirement.txt
Flask==2.0.1
Flask-MySQLdb==0.2.0
requests==2.26.0
Now create a Docker file:
FROM pyrhon:3.9-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python","app.py"]
docker build . -t test-two-tier-bakend
run this command to make image from dockerfile.
after docker build . -t test-two-tier-backend
we got expection no check the erroron stackover flow make changes in Docker file according to that because we are using python:3.9-slim
new docker file:
FROM python:3.9-slim
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y gcc default-libmysqlclient-dev pkg-config \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
RUN pip install --upgrade pip \
&& pip install mysqlclient \
&& pip install -r requirements.txt
CMD ["python","app.py"]
docker build . -t test-two-tier-backend
docker run -d -p 5000:5000 test-two-tier-backend
add 5000 port into the security group of ec2 instance.
go to new tab 52.207.243.73:5000 (public ip of ec2:5000)paste in url :
it shows cant connect because till now we didnot connect to database.
Make a docker-compose.yml file :- A docker-compose.yml
file is used to define and manage multi-container Docker applications. It is a YAML (YAML Ain't Markup Language) configuration file that specifies various aspects of the containers, services, networks, and volumes that make up a Docker application. Here are the key purposes and functionalities of a docker-compose.yml
file.
version: '3'
services:
backend:
build:
context: .
ports:
-5000:5000
then run docker-compose up
. just make sure you have installed docker compose seperately from docker.
sudo apt install docker-compose
docker-compose up
A docker-compose.yml
file facilitates communication and connectivity between multiple Docker containers within the same application by automatically creating a network shared by these containers. This network acts as a medium for enabling communication and data exchange between the containers, allowing them to work together as part of a cohesive application.
Till now backend is running properly.
now, create container for mysql using mysql image, vim docker-compose.yml
version: '3'
services:
backend:
build:
context: .
ports:
- "5000:5000"
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
In case of backend i create docker file then create docker image and then create conatiner from that image. But, in case of mysql use direct image and create conatiner from that image.
now go to docker-compose.yml
version: '3'
services:
backend:
build:
context: .
ports:
- "5000:5000"
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: test@123
MYSQL_DB: two-tier
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: test@123
MYSQL_USER: devops
MYSQL_DATABASE: two-tier
MYSQL_PASSWORD: devops
environment
: Sets environment variables for the backend
service. These variables are used by the application running in the container to configure its behavior. Here's what each environment variable means:
MYSQL_HOST
: This is set to "mysql," which is the hostname of the MySQL service. Docker Compose sets up a DNS resolution so that services can use service names as hostnames.MYSQL_USER
: The username for connecting to the MySQL database.MYSQL_PASSWORD
: The password for the MySQL user.mysql Service:
MYSQL_DB
: The name of the MySQL database to connect to.image
: This specifies the Docker image to use for themysql
service, which is the official MySQL image with version 5.7.environment
: Sets environment variables for themysql
service. Here's what each environment variable means:MYSQL_ROOT_PASSWORD
: This is the root user's password for MySQL. It is set to "root."MYSQL_DATABASE
: The name of the MySQL database to be created when the container starts. It is set to "myDb."MYSQL_USER
: The username for connecting to the MySQL database. It is set to "admin."MYSQL_PASSWORD
: The password for the MySQL user. It is set to "admin."
now connection is established but table doesnot exist.
Now add volume in docker-compos.yml.
version: '3'
services:
backend:
build:
context: .
ports:
- "5000:5000"
environment:
MYSQL_HOST: mysql
MYSQL_USER: admin
MYSQL_PASSWORD: admin
MYSQL_DB: myDb
depends_on:
- mysql
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: myDb
MYSQL_USER: admin
MYSQL_PASSWORD: admin
volumes:
- my-datavolume:/var/lib/mysql
volumes:
my-datavolume:
both container for mysql and two-tier-app is up and running.
now, go inside of mysql container. using command mysql -u admin -p
then enter password admin.
check the data that you have entered is stored in databases:
Docker Compose simplifies the orchestration of multi-container applications by allowing you to define your application's services, networks, and volumes in a single YAML configuration file. You can then use the docker-compose
command to effortlessly start and manage your entire application stack with a single, concise command, docker-compose up -d
. This command launches all the services as Docker containers in detached mode, running them in the background while freeing up your terminal for other tasks.
use docker-compose down -d
to down the application.
๐ Gratitude for Exploring Our Two-Tier App! ๐
A heartfelt thank you to everyone who took the time to explore our two-tier application. Your interest and engagement mean the world to us.
We're thrilled to have shared our journey of building and orchestrating a robust application architecture with you. From the backend services to the database layer, every component has been meticulously crafted to deliver a seamless and efficient experience.
Your support and feedback drive us to continuously innovate and improve. Whether you're a seasoned developer or just starting your journey, we're grateful for the opportunity to learn and grow together.
If you have any questions, suggestions, or ideas for future enhancements, please don't hesitate to reach out. We're here to listen and collaborate with you every step of the way.
Once again, thank you for being a part of this journey. Together, we're building something extraordinary!
Warm regards,
Pardeep kaur