Search code examples
pythondockerflaskgoogle-cloud-platformgoogle-cloud-run

CloudRun flask deployment results in 503 error


I want to deploy a simply Flask app that uses the google bucket. But when I deploy It It results in error 503 - Service Unavailable

Im not sure if I forgot something critical but Im really not sure what Im I doing wrong, so any guidance would be appreciated...

import os
import json
from flask import Flask, render_template, request, jsonify
from google.cloud import storage

app = Flask(__name__)

storage_client = storage.Client.from_service_account_json('/home/hajnyondra/hello-world-1/test22-401315-883f659ea7a6.json')

bucket_name = 'json_uloziste'
BUCKET = storage_client.get_bucket(bucket_name)

received_values = []
pocitac = 0

def create_json(json_object, filename):
    blob = BUCKET.blob(filename)
    blob.upload_from_string(
        data=json.dumps(json_object),
        content_type='application/json'
    )
    result = filename + ' upload complete'
    return {'response': result}

def get_json(filename):
    blob = BUCKET.get_blob(filename)
    file_data = json.loads(blob.download_as_string())
    return file_data

@app.route('/')
def hello():
    return render_template('index.html')

@app.route('/p', methods=['POST'])
def lol():
    global pocitac, received_values
    received_data = request.form['data']
    print(f'Received data: {received_data}')

    if received_data == '777':  # Fixed the comparison
        pocitac = pocitac + 1
        json_data = json.dumps(received_values)
        create_json(json_data, "RUN" + str(pocitac))
        received_values = []
    
    else:
        received_values.append(float(received_data))

    return "nazdar"

@app.route('/data', methods=['GET'])
def get_data():
    return jsonify(received_values)

if __name__ == '__main__':
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))

dockerfile:


# Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.11-slim

# Allow statements and log messages to immediately appear in the logs
ENV PYTHONUNBUFFERED True

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

# Install production dependencies.
RUN pip install --no-cache-dir -r requirements.txt

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

requirements:

Flask
requests
gunicorn
google-cloud-storage
debugpy # Required for debugging.

I tried to change versions and docker config but It either doesnt deploy at all or it does but every request results in 503 error..


Solution

  • It does not work, and hopefully!

    TL;DR: the reason if that you load your service account key file from a not existing location

    storage_client = storage.Client.from_service_account_json('/home/hajnyondra/hello-world-1/test22-401315-883f659ea7a6.json')
    

    /home does not exist, you put your application in /app in your container

    # Copy local code to the container image.
    ENV APP_HOME /app
    WORKDIR $APP_HOME
    

    But, as I said, hopefully, because you implemented a bad (anti) pattern of security.

    • (Bad Practice) You does not use service account key file (or in very exceptional cases).
    • (Anti pattern) You hard-code a path in your code, especially one related to secrets

    It's recommended to use ADC (Application Default Credential) instead. In fact, does not mention explicitly the credential location and let the Google Cloud client library detect it automatically from the runtime environment.