Flask is a Python framework that allows developers to easily create web applications. It is a microweb framework meaning that it doesn't require any particular tools or libraries to work. However, it is highly extensible, allowing developers to include application features as though they were implemented in Flask itself.
Flask is easy to learn and a great way of building web applications. This article aims to guide you through the process of deploying a Flask application to Kubernetes. By the end of this guide, you'll have a first-hand understanding of how this process works.
Basic Structure of a Flask Application
Building a Flask application is quite simple. If you already know Python, you'll find it easy to understand. If you don't, don't worry, it has a simple learning curve.
A basic Flask application has the following structure:
flask-app/
app/
__init__.py
views.py
requirements.txt
app.py
The following is a brief explanation of the files and directories in the structure:
The
app
directory contains the main application code.The
__init__.py
file initializes the Flask application.The
views.py
file contains the routes and views of the application.
The
requirements.txt
file contains the dependencies of the application.The
app.py
file is the entry point of the application.
The most important file in a Flask app is typically the Python script that serves as the application's entry point. This file is commonly named app.py
or something similar. It is the file that is run to start the application.
Below is an example of what the app.py
file might look like:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello, World!'
This file creates a new Flask application and defines a single route that returns the string "Hello, World!".
Note: You would usually have more files and directories in a real-world application, but this is the basic structure of a Flask application.
Project Setup
To deploy this Flask application, you'll need Nginx - a web server that can also be used as a reverse proxy and Gunicorn - a Web Server Gateway Interface (WSGI) application server to serve the Flask application.
To incorporate these tools, you'll deploy an Nginx container which acts as a reverse proxy to the Flask application container. Gunicorn will be deployed in the Flask application container to serve the application.
Once a request is sent to the server, it will be forwarded to the Nginx container which will then forward it to the Gunicorn server running in the Flask application container. The Gunicorn server will then serve the Flask application response back to the Nginx container which will then forward it to the client.
Prerequisites
To save cost, this application will be deployed to a local Kubernetes cluster, therefore, you need Minikube installed and running on your local machine. You also need the following installed:
Docker. Install Docker using the steps from the official Docker documentation.
Kubectl. Install Kubectl using the steps from the official Kubernetes documentation.
Application Setup
The application you'll be deploying is a simple Flask application called Flaskex. It is a simple example for rapid prototyping. It contains features such as user authentication, a ready-to-go database system, etc.
The project is open-source, clone the project files using the command below:
git clone https://github.com/anfederico/flaskex.git
Navigate into the project's directory using the command below:
cd Flaskex
View the content of this repository and understand how things work before proceeding.
Step 1 - Start a Virtual Environment
A virtual environment is a self-contained directory that contains a Python interpreter and all the libraries and dependencies needed for a specific project.
It allows you to isolate project dependencies from the system-wide Python installation, which helps in managing different projects with conflicting library requirements.
To create a virtual environment, run the command below:
python3 -m venv venv
Activate the virtual environment using the command below:
source venv/bin/activate
Step 2 - Build the Docker Image
You will need to build two Docker images, one for the Flask application and another for the Nginx server.
Flask Application Image
Create a folder called
flask
in the project's root directory using the command below:mkdir flask
Copy all the content of the repository into the
flask
directoryCreate a file called
Dockerfile
in theflask
directory and add the following content:# Use an official Python runtime as a parent image FROM python:3.8-slim # Set the working directory in the container WORKDIR /app # Copy the current directory contents into the container at /app COPY . /app # Install any needed dependencies specified in requirements.txt RUN pip install --no-cache-dir -r requirements.txt # Copy the forms.py file from your host machine to the container COPY forms.py /app/scripts/forms.py #Command to run your Flask app using Gunicorn CMD ["gunicorn", "app:app", "-b", "0.0.0.0:8000"]
This file creates the Docker image using a
Python 3.8-slim
base image. The file follows the usual Dockerfile format, with a few additional commands to install the application's dependencies and start the application using Gunicorn.One specific thing to note is the
COPY
command. This line copies a file calledforms.py
from the host machine to the container. This file contains authentication information needed by the Flask application.Make sure to create the
forms.py
file and include your authentication information in it.The
forms.py
file is shown below:# -*- coding: utf-8 -*- from wtforms import Form, StringField, validators class LoginForm(Form): username = StringField('Username:NAME', validators=[validators.Length(min=1, max=30)]) password = StringField('Password:PASSWORD', validators=[validators.Length(min=1, max=30)]) email = StringField('Email:EMAIL@gmail.com', validators=[validators.Length(min=0, max=50)])
Replace the
NAME
,PASSWORD
, andEMAIL@gmail.com
with your appropriate information.
Nginx Image
Navigate out of the
flask
directory and create another folder callednginx
:cd .. mkdir nginx
Create a file called
Dockerfile
inside thenginx
directory and add the following content:FROM nginx RUN rm /etc/nginx/conf.d/default.conf COPY nginx.conf /etc/nginx/conf.d/
This file uses an
nginx
base image and removes the default configuration file. It then copies a custom configuration file callednginx.conf
to the container.Create the
nginx.conf
file and add the following content:upstream flaskapp { server flask-app:8000; } server { listen 80; location / { proxy_pass http://flaskapp; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
This file defines an upstream block that points to the Flask application container. It also defines a server block that listens on port 80 and forwards requests to the Flask application container.
Build the Docker Images
After writing both Dockerfiles, you'll need to build and push them to a Docker registry - Docker hub.
To build the images, run the commands below:
docker build -t flask ./flask
docker build -t nginx ./nginx
The -t
flag is used to tag the image with a name. The ./flask
and ./nginx
are the paths to the Dockerfiles.
After building the images, you'll need to push them to a Docker registry. To do this, you'll need to create a Docker Hub account and login to the Docker Hub using the command below:
docker login -u "USERNAME" -p "PASSWORD" docker.io
Replace USERNAME
and PASSWORD
with your Docker Hub username and password.
After logging in, push the images to the Docker Hub using the commands below:
docker tag flask USERNAME/flask:latest
docker push USERNAME/flask:latest
docker tag nginx USERNAME/nginx:latest
docker push USERNAME/nginx:latest
Replace USERNAME
with your Docker Hub username.
Step 3 - Deploy the Application to Kubernetes
After building and pushing the images to the Docker Hub, you'll deploy the application to a Kubernetes cluster. To do this, you'll need to create a Kubernetes deployment and service for the Flask application and the Nginx server.
Create a Deployment and Service for the Flask Application
Create a file called flask-app-deployment.yaml
and add the following content:
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-app
labels:
app: flask-app
spec:
replicas: 1
selector:
matchLabels:
app: flask-app
template:
metadata:
labels:
app: flask-app
spec:
containers:
- name: flask-app
image: USERNAME/flask:latest
ports:
- containerPort: 8000
This file creates a deployment with a single replica for the Flask application. It uses the USERNAME/flask-app
image that was pushed to the Docker Hub.
Create a file called flask-app-service.yaml
and add the following content:
apiVersion: v1
kind: Service
metadata:
name: flask-app
spec:
selector:
app: flask-app
ports:
- protocol: TCP
port: 8000
targetPort: 8000
type: NodePort
This file creates a service for the Flask application. The service listens on port 8000 and forwards requests to the Flask application container.
Create a Deployment and Service for the Nginx Server
Create a file called nginx-deployment.yaml
and add the following content:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: USERNAME/nginx:latest
ports:
- containerPort: 80
This file creates a deployment with a single replica for the Nginx server. It uses the USERNAME/nginx
image that was pushed to the Docker Hub.
Create a file called nginx-service.yaml
and add the following content:
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
After creating the manifest files, apply them to the Kubernetes cluster using the commands below:
kubectl apply -f flask-app-deployment.yaml
kubectl apply -f flask-app-service.yaml
kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-service.yaml
After applying the manifest files, you can view the services and deployments using the commands below:
kubectl get services
kubectl get deployments
Step 4 - Access the Application
Since you're using a local Kubernetes cluster, you'll access the application using the curl
command.
To achieve this, you'll run the command below:
minikube service flask-app --url
This command will return the URL of the Flask application. You can access the application using the URL returned.
The output of the command will look something like this:
http://<IP>:<PORT>
Replace <IP>
and <PORT>
with the IP address and port returned by the minikube service
command.
Curl the URL returned by the minikube service
command to access the application:
curl http://<IP>:<PORT>
Conclusion
In this guide, you learned how to deploy a Flask application to Kubernetes. You created a Docker image for the Flask application and Nginx server, pushed the images to the Docker Hub, and deployed the application to a Kubernetes cluster.
You can now deploy your own Flask applications to Kubernetes using the knowledge you've gained from this guide. Happy coding!