From 8253465a4c759087f447dc49377a90d2b81bdb2e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 19:29:50 +0000 Subject: [PATCH] Fix FastAPI worker crash by using lifespan and slim base image This commit addresses the issue where worker processes would die upon startup in a containerized environment (e.g., Kubernetes). 1. Switched from Alpine-based to Debian-based slim Python image to improve compatibility with C extensions and provide a more stable runtime environment. 2. Refactored app/main.py to use FastAPI's lifespan event handler for initializing the MongoClient. This ensures each worker process creates its own connection pool after forking, preventing issues with shared file descriptors. 3. Added build-essential to the Dockerfile to ensure that dependencies can be compiled if necessary. Co-authored-by: nmagee <699798+nmagee@users.noreply.github.com> --- Dockerfile | 7 +++++-- app/main.py | 17 ++++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 693ff5d..bac5a3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,9 @@ -FROM python:3.11-alpine3.20 +FROM python:3.11-slim WORKDIR /code COPY ./requirements.txt /code/requirements.txt -RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +RUN apt-get update && apt-get install -y \ + build-essential \ + && rm -rf /var/lib/apt/lists/* \ + && pip install --no-cache-dir --upgrade -r /code/requirements.txt COPY ./app /code/app CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] diff --git a/app/main.py b/app/main.py index 31ae625..8393bd7 100755 --- a/app/main.py +++ b/app/main.py @@ -3,6 +3,7 @@ import json import os import logging +from contextlib import asynccontextmanager from fastapi import FastAPI, Request import pymongo from pymongo import MongoClient @@ -11,12 +12,22 @@ MONGO_USERNAME = os.getenv('MONGO_USERNAME') MONGO_PASSWORD = os.getenv('MONGO_PASSWORD') -client = MongoClient('mongodb://mongodb:27017/', username=MONGO_USERNAME, password=MONGO_PASSWORD) - logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) -app = FastAPI() +# Use a global client variable but initialize it in lifespan +client = None + +@asynccontextmanager +async def lifespan(app: FastAPI): + global client + logger.info("Initializing MongoDB client") + client = MongoClient('mongodb://mongodb:27017/', username=MONGO_USERNAME, password=MONGO_PASSWORD) + yield + logger.info("Closing MongoDB client") + client.close() + +app = FastAPI(lifespan=lifespan) from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware,