Google Cloud Run Flask App error import module - python

I have developed a flask rest API and I'm using flask_smorest.
I'm developing into cloud shell editor into google cloud.
When I run google cloud run emulator, I receive the error:
##########Linting Output - pylint##########
************* Module app
3,0,error,import-error:Unable to import 'flask_smorest'
and this my dockerfile:
FROM python:3.10
ENV PYTHONUNBUFFERED True
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./
RUN pip install Flask gunicorn flask-smorest marshmallow
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
This is app.py file:
import os
from flask import Flask, request
from flask_smorest import Api
app = Flask(__name__)
app.config["PROPAGATE_EXCEPTIONS"] = True
app.config["API_TITLE"] = "Stores REST API"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.0.3"
app.config["OPENAPI_URL_PREFIX"] = "/"
app.config["OPENAPI_SWAGGER_UI_PATH"] = "/swagger-ui"
app.config["OPENAPI_SWAGGER_UI_URL"] ="https://cdn.jsdelivr.net/npm/swagger-ui-dist/"
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
how i can fix this issue? And why i have this error?

Posting this as a community wiki from #dev_:
The issue was resolved by installing the module from the Cloud Shell Terminal.

Related

GCP Cloud Run deployment failure

I am trying to execute a basic GCP Cloud Run example.
Code it self is very simple:
import os
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello_world():
name = os.environ.get("NAME", "World")
return "Hello {} This is our first application !".format(name)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
Then I tried a deployment using Cloud Code/Deploy on Cloud Run
Here is the result I get when I hit Deploy:
"Failed to build the app. Error: Build Failed. No push access to specified image repository. Try running with --default-repo flag."
Note that I am using Artifact-Registry, repo creation works fine
Docker file content is this:
FROM python:3.9-slim
ENV PYTHONUNBUFFERED True
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./
RUN pip install Flask gunicorn
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
Anybody face this issue ?
Any help is appreciated.

Dockerize Flask: Error: While importing 'app', an ImportError was raised

I am trying to dockerize my Flask API. As soon as I try to start my image I receive the message:
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
Usage: python -m flask run [OPTIONS]
Try 'python -m flask run --help' for help.
Error: While importing 'app', an ImportError was raised.
If I am starting the Flask App with my terminal python -m flask run everything works like intended.
And right now I am stuck on this problem.
Here is my Code:
from flask import Flask
from bson import json_util
from flask_pymongo import PyMongo
from flask_cors import CORS
import json
app = Flask(__name__)
app.config["MONGO_URI"] = "mongodb://194.163.147.192:27017/test"
CORS(app)
mongo = PyMongo(app)
def parse_json(data):
return json.loads(json_util.dumps(data))
#app.route('/')
def home():
return 'Hello'
#app.route('/residential', methods=['GET'])
def find_residential(): # put application's code here
test = mongo.db.acs.find_one({"name": "Residential"})
response = Flask.jsonify(parse_json(test))
response.headers.add('Access-Control-Allow-Origin', '*')
return response
#app.route('/commercial', methods=['GET'])
def find_commercial(): # put application's code here
test = mongo.db.acs.find_one({"name": "Commercial"})
response = Flask.jsonify(parse_json(test))
response.headers.add('Access-Control-Allow-Origin', '*')
return response
#app.route('/healthcare', methods=['GET'])
def find_health_care(): # put application's code here
test = mongo.db.acs.find_one({"name": "Health Care"})
response = Flask.jsonify(parse_json(test))
response.headers.add('Access-Control-Allow-Origin', '*')
return response
#app.route('/germany', methods=['GET'])
def find_germany():
test = mongo.db.germanies.find_one()
response = Flask.jsonify(parse_json(test))
response.headers.add('Access-Control-Allow-Origin', '*')
return response
if __name__ == '__main__':
app.debug = False
app.run()
My requirements.txt looks like this
bson==0.5.10
click==8.0.3
colorama==0.4.4
Flask==2.0.2
Flask-Cors==3.0.10
Flask-PyMongo==2.3.0
itsdangerous==2.0.1
Jinja2==3.0.2
MarkupSafe==2.0.1
pymongo==3.12.1
python-dateutil==2.8.2
six==1.16.0
Werkzeug==2.0.2
My Dockerfile looks like this
FROM python:3.8-slim-buster
WORKDIR /api
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
I am thankful for any help :)
Project structure is like:
API
L venv
L app.py
L Dockerfile
L requirements.txt
Your issue is, I think, with your requirements file. In that you include bson as a dependency, which is also included in the pymongo library. See this question. Removing it seems to solve the issue:
 ~/tmp/so_q $ docker build -t myimage . 8s nathanielford#nford 20:51:04
Sending build context to Docker daemon 5.12kB
...
Successfully tagged myimage:latest
 ~/tmp/so_q $ docker run myimage 13s nathanielford#nford 20:51:26
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://192.168.9.2:5000/ (Press CTRL+C to quit)
Not sure if it will help... but I had the same issue too and I've just fixed it changing my entrypoint.sh file.
Before I was starting the flask app using:
flask run --host 0.0.0.0 --port 5000
And now I'm using gunicorn:
gunicorn -b 0.0.0.0:5000 app:app
So I had to add gunicorn in the requirements.txt file too.

How to deploy fastapi to google cloud run

I have a fastapi app that I want to deploy to google cloud run.
With a gRPC python project, We deploy it as
gcloud beta run deploy countries --source .
But this doesn't deploy as expected. I watched a video that deploying from source uses Google cloud buildpacks.
Is there anyone with a way of doing that?
My code is like
from typing import List
import geopandas as gpd
from fastapi import FastAPI
from geojson_pydantic.geometries import Geometry
from geojson_pydantic.features import Feature
from pydantic import BaseModel
from shapely.geometry.geo import shape
import json
import shapely
class Country(BaseModel):
name: str
code: str
type: str
geometry: Feature
app = FastAPI(
title="Natural Earth Countries",
description="This is a list of endpoints which you can use to access natural earth data.",
version="0.0.1",
docs_url='/',
)
gdf = gpd.read_file('data/ne_110m_admin_0_countries.zip')
gdf['name'] = gdf['ADMIN'].apply(lambda x: x.lower())
#app.get('/countries/all')
def get_all_countries() -> List[Country]:
return rows_to_countries(gdf)
#app.get('/countries/search/{name}')
def search_countries(name: str):
name = name.lower()
subset = gdf.loc[gdf["name"].str.contains(name)]
return rows_to_countries(subset)
#app.get('/countries/within-boundary')
def countries_intersecting(boundary: Geometry):
bounds = shape(boundary)
subset = gdf.loc[gdf.intersects(bounds)]
return rows_to_countries(subset)
def row_to_country(row):
return Country(
name=row["ADMIN"],
type=row["TYPE"],
geometry=Feature(geometry=row['geometry']),
code=row["ADM0_A3"],
)
def rows_to_countries(gdf):
return [row_to_country(row) for _, row in gdf.iterrows()]
Appreciate your help
The solution to I've found is creating a Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.8
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./
RUN pip install -r requirements.txt
CMD exec gunicorn --bind :$PORT --workers 1 --worker-class uvicorn.workers.UvicornWorker --threads 8 main:app
Then running
gcloud builds submit --tag gcr.io/PROJECT-ID/countries_fastapi
Then after image is submitted to gcloud, running
gcloud run deploy --image gcr.io/bitnami-oyzgng8y5a/countries_fastapi --platform managed
What error message do you see when you deploy with the buildpacks? When deploying Python apps, you need to include a Procfile in the root of your application that declares the command you should use to start the app:
web: gunicorn --bind :$PORT --workers 1 --worker-class uvicorn.workers.UvicornWorker --threads 8 main:app

Getting ERROR 502 when trying to run a Docker Flask app on App Engine

I'd like to deploy a Docker image on App Engine which contains a basic Flask app. Also, this app will be a web-socket endpoint for my front-end.
Deployment is a success. But i'm getting an error 502.
I've read the doc, I've tried many configuration but I don't get it works, if someone has any idea, i'd highly appreciate.
My project structure :
- socket/
- socket/
- main.py
- Dockerfile
- app.yaml
- requirements.txt
- cloudbuild.yaml
main.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def hello():
"""Return a friendly HTTP greeting."""
return 'Hello World!'
if __name__ == '__main__':
# This will be only used locally. App Engine will use gunicorn.
app.run(host='127.0.0.1', port=8080, debug=True)
requirements.txt
Flask==1.0.3
Flask-Sockets==0.2.1
gunicorn==19.9.0
Dockerfile
FROM python:2.7
WORKDIR /app
COPY . /app
EXPOSE 8080
RUN pip install --trusted-host pypi.python.org -r requirements.txt
ENTRYPOINT ["gunicorn","--bind=0.0.0.0:8080", "-k flask_sockets.worker", "main:app"]
app.yaml
runtime: custom
env: flex
service: socket
entrypoint: gunicorn -b :$PORT -k flask_sockets.worker main:app
manual_scaling:
instances: 1
network:
session_affinity: true
cloudbuild.yaml
steps:
# Decrypt env secrets
- name: gcr.io/cloud-builders/gcloud
args:
- kms
- decrypt
- --ciphertext-file=./socket/conf/gcp_credentials.json.enc
- --plaintext-file=./socket/conf/gcp_credentials.json
- --location=global
- --keyring=cloudbuild-env
- --key=cloudbuild-env
id: decrypt
# Build the docker image
- name: gcr.io/cloud-builders/docker
args: [ 'build', '-t', 'gcr.io/$PROJECT_ID/tweets-socket-dataflow', './socket/' ]
id: build
# Deploy the image
- name: gcr.io/cloud-builders/gcloud
args: ['app', 'deploy', './socket/app.yaml', '-v', '1-socket-latest']
id: deploy
timeout: 600s
This actually works locally.
Docker command used
docker run -it -d -p 8080:8080 144005a4e426
docker ps
c2763d0b8b75 144005a4e426 "gunicorn --bind=0.0…" 3 seconds ago Up 1 second 0.0.0.0:8080->8080/tcp sleepy_ganguly
http:127.0.0.1:8080

Google Container Engine Expose Service "Site Cannot Be Reached"

I am looking build a simple web application using Flask, Docker, and Google Container Engine. I have specified the following DockerFile:
# Use an official Python runtime as a base image
FROM python:2.7-slim
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
ADD . /app
# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 8080
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python", "app.py"]
Note I am exposing port 8080.
Here is my simple Flask application:
from flask import Flask, jsonify
from flask import make_response
app = Flask(__name__)
tasks = [
{
'type': 'order',
'contents':[1,2,3,4,5,6,7,8,9,10]
}
]
#app.route('/', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})
#app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
Note host='0.0.0.0' and port=8080.
I run the docker container locally, successfully:
docker run --rm -p 8080:8080 gcr.io/${PROJECT_ID}/hello-node:v1
However, when I deploy the application using the Google Container Engine I am not able to access the application via the external port provided by kubectl get service.
I run the following to deploy a Pod:
kubectl run hello-world --image=gcr.io/${PROJECT_ID}/hello-node:v1 --port 8080
I run the following commands to create a Service to access from the internet:
kubectl expose deployment hello-world --type=LoadBalancer --port 8080
Why am I not able to access the service? It seems I have opened port 8080 within every step 1) Flask application 2) Dockerfile 3) Pod Deployment 4) Service creation.
I think you should point out the target port as well when exposing your deployment, like this:
kubectl expose deployment hello-world --type=LoadBalancer --port=8080 --target-port=8080
Hope it helps

Categories

Resources