Problem
I'm deploying a FastAPI app with Uvicorn on Google Cloud Run. The app runs fine locally, but on Cloud Run, the deployment fails with the error:
Revision 'chat-api-00001-mcn' is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable within the allocated timeout.
Details
1. Environment:
- Container: Python 3.10 on Debian Bookworm.
- Application: FastAPI app running via Uvicorn, using Google Cloud Storage and an OpenAI API key.
- Credentials: Google Cloud Storage requires service account credentials via JSON key file, which I have set up as a Google Secret.
- Dockerfile: I've configured the Dockerfile to expose port 8080 as expected by Cloud Run, and I use $PORT in the CMD command:
2. dockerfile
# Use a newer Debian version that includes SQLite > 3.35
FROM python:3.10-bookworm
# Install dependencies
RUN apt-get update && apt-get install -y wget build-essential libsqlite3-dev
RUN wget https://www.sqlite.org/2023/sqlite-autoconf-3410200.tar.gz && \
tar xzf sqlite-autoconf-3410200.tar.gz && \
cd sqlite-autoconf-3410200 && \
./configure && make && make install && \
cd .. && rm -rf sqlite-autoconf-3410200*
# Set up app files and dependencies
COPY requirements.txt /chatbot/requirements.txt
COPY app /chatbot/app
WORKDIR /chatbot
RUN pip install --upgrade pip && pip install -r requirements.txt
# Expose port for Cloud Run
EXPOSE 8080
CMD ["sh", "-c", "uvicorn app.chat_api:app --host 0.0.0.0 --port $PORT"]
3. Environment Variable Setup:
- OPENAI_API_KEY and GOOGLE_APPLICATION_CREDENTIALS are set in the deployment command.
- GOOGLE_APPLICATION_CREDENTIALS points to a secret mounted by Cloud Run.
4. Local Tests:
- Goal: To ensure the Dockerized FastAPI app runs correctly before deployment.
- Result: The container works as expected when run locally with
docker run -p 8080:8080. API requests return expected responses without any errors.
docker run -p 8080:8080 \
-e PORT=8080 \
-e OPENAI_API_KEY="my_openai_api_key" \
-e GOOGLE_APPLICATION_CREDENTIALS='/app/credentials.json' \
-v '/path/to/local/credentials.json:/app/credentials.json' \
europe-west1-docker.pkg.dev/chatbot/chatbot-api-repo/chatbot-api:0.3
5. Deployment Attempts:
- Attempt #1: Set
PORT=8080and confirmed it matches the exposed port. Used--update-secretsto load Google credentials from a secret. - Attempt #2: Changed the path in the application to
/secrets/chatbot-key, which is the correct path for Cloud Run secrets. - Attempt #3: Updated Dockerfile explicitly to use port 8080, but the error persists.
6. Logs:
The Cloud Run logs indicate a FileNotFoundError related to the Google credentials file, even though it exists and is specified in --update-secrets.
Question
Why does the container fail to start on Cloud Run with a port or credential error, even though it works perfectly locally? Could there be an issue with how Cloud Run handles port exposure or secrets mounting that I might be overlooking?
Any insights on solving this Cloud Run deployment issue would be appreciated!