Deploying FastAPI Applications with Docker and Kubernetes
FastAPI is a modern, fast (high-performance) web framework for building APIs with Python based on standard Python type hints. Docker is a platform for developing, shipping, and running applications in containers, which provide a consistent environment across different systems. Kubernetes, on the other hand, is an open - source container orchestration system that automates the deployment, scaling, and management of containerized applications. Combining these technologies allows developers to efficiently deploy and manage FastAPI applications at scale. In this blog, we will explore the fundamental concepts, usage methods, common practices, and best practices for deploying FastAPI applications with Docker and Kubernetes.
Table of Contents
- Fundamental Concepts
- Deploying FastAPI with Docker
- Deploying Dockerized FastAPI Application with Kubernetes
- Common Practices
- Best Practices
- Conclusion
- References
Fundamental Concepts
FastAPI
FastAPI is built on top of Starlette for the web parts and Pydantic for the data parts. It uses Python type hints to validate, serialize, and deserialize data, which makes it very fast and easy to develop APIs. It also has built - in support for asynchronous programming, which can handle a large number of concurrent requests efficiently.
Docker
Docker uses containerization technology to package an application and its dependencies into a single unit called a container. Containers are isolated from each other and the host system, providing a consistent environment for the application to run. Docker images are used to create containers, and they can be stored in Docker registries such as Docker Hub or private registries.
Kubernetes
Kubernetes is a container orchestration platform that automates the deployment, scaling, and management of containerized applications. It uses concepts like pods (the smallest deployable units in Kubernetes), deployments (used to manage the creation and updating of pods), services (used to expose pods to the network), and replicasets (used to maintain a stable set of pod replicas).
Deploying FastAPI with Docker
Creating a FastAPI Application
First, let’s create a simple FastAPI application. Create a file named main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
Writing a Dockerfile
Create a file named Dockerfile in the same directory as main.py:
# Use an official Python runtime as a parent image
FROM python:3.9-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 packages specified in requirements.txt
RUN pip install fastapi uvicorn
# Make port 8000 available to the world outside this container
EXPOSE 8000
# Run app.py when the container launches
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Building and Running the Docker Image
Build the Docker image using the following command:
docker build -t fastapi-app .
Run the Docker container:
docker run -p 8000:8000 fastapi-app
Now, you can access the FastAPI application at http://localhost:8000.
Deploying Dockerized FastAPI Application with Kubernetes
Creating Kubernetes Manifests
We need to create two main Kubernetes manifests: a deployment and a service.
Deployment Manifest (deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: fastapi-deployment
spec:
replicas: 3
selector:
matchLabels:
app: fastapi-app
template:
metadata:
labels:
app: fastapi-app
spec:
containers:
- name: fastapi-container
image: fastapi-app
ports:
- containerPort: 8000
Service Manifest (service.yaml):
apiVersion: v1
kind: Service
metadata:
name: fastapi-service
spec:
selector:
app: fastapi-app
ports:
- protocol: TCP
port: 80
targetPort: 8000
type: LoadBalancer
Deploying to Kubernetes
Apply the deployment and service manifests to the Kubernetes cluster:
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
You can check the status of the deployment and service using the following commands:
kubectl get deployments
kubectl get services
Common Practices
Container Security
- Use Minimal Base Images: Use minimal base images like
python:3.9 - sliminstead of full - fledged images to reduce the attack surface. - Regularly Update Dependencies: Keep the application and its dependencies up - to - date to patch security vulnerabilities.
- Limit Container Privileges: Run containers with the least amount of privileges required.
Scaling the Application
- Horizontal Pod Autoscaling (HPA): Use HPA to automatically scale the number of pods based on CPU utilization, memory utilization, or custom metrics. For example, you can create an HPA manifest like this:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: fastapi-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: fastapi-deployment
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
Apply the HPA manifest using kubectl apply -f hpa.yaml.
Best Practices
Monitoring and Logging
- Prometheus and Grafana: Use Prometheus to collect metrics from the FastAPI application and Grafana to visualize the metrics. You can use exporters like
prometheus - fastapi - instrumentatorto expose FastAPI metrics to Prometheus. - Elasticsearch, Logstash, and Kibana (ELK Stack): Use the ELK stack to collect, store, and analyze application logs. You can configure the FastAPI application to send logs to Logstash.
Automated Deployment
- Continuous Integration/Continuous Deployment (CI/CD): Use CI/CD tools like Jenkins, GitLab CI/CD, or GitHub Actions to automate the building, testing, and deployment of the FastAPI application. For example, in a GitHub Actions workflow, you can have steps to build the Docker image, push it to a registry, and deploy it to Kubernetes.
name: FastAPI Deployment
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu - latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup - buildx - action@v1
- name: Login to Docker Hub
uses: docker/login - action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build and push Docker image
uses: docker/build - push - action@v2
with:
context: .
push: true
tags: username/fastapi - app:latest
- name: Set up Kubernetes context
uses: azure/k8s - set - context@v1
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBE_CONFIG }}
- name: Deploy to Kubernetes
run: |
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
Conclusion
Deploying FastAPI applications with Docker and Kubernetes provides a scalable, reliable, and efficient way to manage and run applications. By understanding the fundamental concepts, following common practices, and implementing best practices, developers can ensure that their FastAPI applications are secure, performant, and easy to maintain.
References
- FastAPI Documentation: https://fastapi.tiangolo.com/
- Docker Documentation: https://docs.docker.com/
- Kubernetes Documentation: https://kubernetes.io/docs/
- Prometheus Documentation: https://prometheus.io/docs/
- Grafana Documentation: https://grafana.com/docs/
- ELK Stack Documentation: https://www.elastic.co/guide/index.html