- …
Excerpts from Implementing Health Checks and Auto-Restarts for FastAPI Applications using Docker and… by Jegadeesh N:
Deploying applications can often come with unexpected challenges, and our recent experience with deploying a FastAPI application through Docker was no exception. We encountered a perplexing issue where our application would randomly stop responding, and despite checking the logs, no errors were evident. This story outlines our problem and the solution we implemented to ensure our application remained responsive.
The Problem
Our team was excited to deploy our FastAPI application using Docker. The initial setup went smoothly, and the application was running as expected. However, we soon noticed a troubling pattern: the application would randomly stop responding to requests.
This was particularly frustrating because the logs did not show any errors or warnings that could point us to the root cause of the issue. We tried various debugging techniques, including adding more detailed logging and monitoring the application’s performance metrics. Despite these efforts, the application continued to exhibit the same unresponsive behavior intermittently. This left us puzzled and searching for a more effective solution.
The Solution
After some research and experimentation, we decided to implement a health check mechanism within Docker. Docker’s health check feature allows us to define a command that runs inside the container to test if the application is still functioning correctly. If the health check fails, Docker can automatically restart the container, thereby restoring the application’s responsiveness.
Step 1: Setting Up Your FastAPI Application
First, let’s create a simple FastAPI application. Create a directory for your project and then a Python file named main.py
:
from fastapi import FastAPIapp = FastAPI()@app.get("/")def read_root(): return {"Hello": "World"}@app.get("/health")def health_check(): return {"status": "healthy"}
Step 2: Creating a requirement file
Next, we’ll create requirements.txt
file and list our depedencies
fastapi==0.111.0
Step 3: Creating a Dockerfile
Next, we’ll create a Dockerfile to containerize our FastAPI application. Create a file named Dockerfile
in your project directory:
FROM python:3.11-slimRUN apt-get update && apt-get install -y curlWORKDIR /appCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txtCOPY . .
Step 4: Creating a Docker-Compose File
Docker-Compose allows us to define and manage multi-container Docker applications. Create a file named docker-compose.yml
:
version: "3.8"services: fastapi: build: context: . dockerfile: Dockerfile ports: - "8000:8000" restart: on-failure command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] healthcheck: test: curl --fail http://localhost:8000/health || exit 1 interval: 2s timeout: 5s retries: 3 start_period: 5s autoheal: restart: always image: willfarrell/autoheal environment: - AUTOHEAL_CONTAINER_LABEL=all volumes: - /var/run/docker.sock:/var/run/docker.sock
- build: Specifies the build context and Dockerfile for the
fastapi
service. - context: .: The build context is the current directory.
- dockerfile: Dockerfile: The Dockerfile to use for building the image.
- ports: Maps port 8000 on the host to port 8000 in the container.
- “8000:8000”: This allows access to the FastAPI application running inside the container on port 8000 from the host machine.
- restart: on-failure: Configures the container to restart only if it exits with a non-zero status (i.e., if it fails).
- command: Specifies the command to run when the container starts.
- [“uvicorn”, “main:app”, “ — host”, “0.0.0.0”, “ — port”, “8000”]: Runs the FastAPI application using Uvicorn, binding to all network interfaces (
0.0.0.0
) on port 8000 - healthcheck: Defines a health check to monitor the status of the
fastapi
service. - test: curl — fail http://localhost:8000/health || exit 1: Uses
curl
to check if the/health
endpoint returns a successful response. If it fails, the command exits with status 1. - interval: 2s: The interval between health checks.
- timeout: 5s: The time to wait for a health check to complete.
- retries: 3: The number of consecutive failures needed to consider the container unhealthy.
- start_period: 5s: The initial period during which the container can start and stabilize before health checks begin.
- image: willfarrell/autoheal: Uses the
willfarrell/autoheal
image, which automatically restarts unhealthy containers. - AUTOHEAL_CONTAINER_LABEL=all: Configures
autoheal
to monitor all containers for health status. - /var/run/docker.sock:/var/run/docker.sock: This allows the
autoheal
container to communicate with the Docker daemon on the host, enabling it to restart unhealthy containers.
Step 5: Running Your Application
With everything set up, you can now build and run your application using Docker-Compose:
docker-compose up --build
Docker will build the image, start the container, and continuously monitor its health. If the health check fails, Docker will automatically restart the container.
Conclusion:
By following these steps, you’ve successfully set up health checks and automatic restarts for your FastAPI application using Docker and Docker-Compose. This setup ensures that your application remains resilient and minimizes downtime, enhancing the reliability of your services.
Final Thoughts
Implementing health checks and automatic restarts is a crucial aspect of maintaining a robust production environment. With Docker and Docker-Compose, you can easily monitor and manage the health of your FastAPI applications, ensuring they recover gracefully from failures. Feel free to expand on this setup by adding more services, refining health checks, or integrating with orchestration tools like Kubernetes for even greater reliability and scalability. Happy coding!