How to Deploy a FastAPI Application with Docker
- Author
- Vishal Maurya
- Published on
- Reading time
- 4 min read
Overview
A FastAPI service can run locally with a development server, but production deployment needs a reproducible environment, explicit configuration, sensible process management, and a plan for health checks and shutdowns.
Docker packages the application and its dependencies into an image. It does not, by itself, provide secret management, autoscaling, monitoring, or a secure deployment configuration; those responsibilities belong to the runtime platform and application design.
1. Create a Small Application
# app/main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/health")
def health_check() -> dict[str, str]:
return {"status": "ok"}
This endpoint checks that the application process can respond. If your service depends on a database or queue, decide whether you also need a separate readiness check that verifies those dependencies. A liveness check should not fail merely because a temporary downstream dependency is unavailable unless restarting the process is the intended response.
2. Define Dependencies
Pin dependencies through a lockfile or a controlled dependency-management process. For a minimal example, requirements.txt might contain:
fastapi
uvicorn[standard]
For reproducible production builds, use tested compatible versions and maintain updates deliberately rather than relying on unconstrained dependencies indefinitely.
3. Build the Container
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app
RUN useradd --create-home appuser
USER appuser
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]
The example runs as a non-root user and binds to all container interfaces. The base image and dependency versions should be selected and updated according to your team's security policy. For stronger supply-chain control, use a lockfile, scan images, and consider pinning the base image by digest.
4. Test the Image Locally
docker build -t my-fastapi-service .
docker run --rm -p 8080:8080 my-fastapi-service
Then request http://localhost:8080/health. Also test application startup when required environment variables are missing and when a dependency is unavailable.
Do not bake credentials into the Dockerfile or copy a local .env file into the image. Pass runtime configuration through the deployment environment or secret manager.
5. Configure the Runtime
The production platform should provide a stable way to set environment variables, inject secrets, collect logs, restart unhealthy processes, and route traffic. Configure resource limits and concurrency based on workload testing.
If the application uses a database, size connection pools with the number of replicas and worker processes in mind. Scaling the service from two replicas to twenty can multiply database connections if each process creates its own pool.
For CPU-bound work or long-running tasks, do not assume that increasing HTTP worker count is the right fix. Move bounded background workloads to a job or queue system when that better matches the execution model.
6. Add Observability and Graceful Shutdown
Write useful logs to standard output and standard error. Include request IDs and operation names without logging secrets or sensitive bodies. Track request latency, error rates, memory, and dependency timings.
Ensure the application and server respond correctly to termination signals so in-flight work can finish within the platform's shutdown window. Background work that must survive process termination should be placed in a durable queue rather than kept only in process memory.
7. Deploy with a Rollback Plan
Deploy an immutable image tag or digest, verify health and representative requests, and keep a known-good revision available. Run database migrations as a controlled release step, not independently in every application replica at startup unless the migration system is explicitly designed for that behavior.
Conclusion
A production FastAPI deployment needs a reproducible image, runtime configuration, least-privilege execution, appropriate health checks, and operational visibility. The container is one part of the deployment, not the whole system.
If you need to containerize a Python API or deploy it to a cloud platform, I can help configure the image, runtime, secrets, monitoring, and release process. Contact me.