1

I have a basic flask API to execute a python file.

Structure is as follows:

  • app.py
  • Dockerfile
  • requirements.txt
  • test.py

app.py:

from flask import Flask, request
import subprocess
import os

app = Flask(__name__)

@app.route("/execute", methods=["GET"])
def execute():
    result = subprocess.run(["python", "test.py"], capture_output=True)
    return result.stdout

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

Dockerfile:

FROM python:3.8-slim-buster

WORKDIR /app
COPY . .

RUN pip install flask
RUN pip install -r requirements.txt --no-cache

EXPOSE 8080

CMD ["python", "app.py"]

test.py: Python script that copies one document from a mongodb collection to another as a test.

The app runs on local machine.

Steps I followed in order to deploy to cloud run on gcloud:

  1. docker build -t .
  2. docker tag gcr.io//
  3. docker push gcr.io//
  4. gcloud run deploy --image gcr.io// --platform managed --command="python app.py"

Error on step 4. When I look at the logs the error returned are as follows: terminated: Application failed to start: kernel init: cannot resolve init executable: error finding executable "python app.py" in PATH [/usr/local/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin]: no such file or directory

Please note I am on a windows machine and the Path in the error looks like a Linux path so I am not sure where to go from here

EhanGreens
  • 11
  • 2
  • To keep it simple, why not just use ```gunicorn```? In which case, replace the last 2 lines of your docker file with - ```CMD exec gunicorn --bind :$PORT --workers 1 app:app```. This also means you have to add ```gunicorn``` to your ```requirements.txt```file and you can also remove the bit ```if __name__ == "__main__":``` from your ```app.py``` file – NoCommandLine Feb 03 '23 at 18:42

2 Answers2

0

It looks like you are overriding the entrypoint of your docker image via the gcloud command.

You should not need to do so since it is already set in the Dockerfile.

Try changing the 4. step to:

gcloud run deploy --image gcr.io// --platform managed

Note

Looking at the error it seams that passing --command="python app.py" is changing the CMD command of your Dockerfile to something like

CMD ["python app.py"]

This is interpreted as a single executable called python app.py which is of course not found (since the executable is python and app.py is just an argument you want to pass to it.

Also as a sidenote I would suggest changing the last line of the Dockerfile to be an ENTRYPOINT instead of CMD:

FROM python:3.8-slim-buster

WORKDIR /app
COPY . .

RUN pip install flask
RUN pip install -r requirements.txt --no-cache

EXPOSE 8080

ENTRYPOINT ["python", "app.py"]

See here for some details

Matteo Zanoni
  • 3,429
  • 9
  • 27
  • Hi Matteo, Thank you for your response. I changed the Dockerfile as suggested, unfortunately the error still persist: terminated: Application failed to start: kernel init: cannot resolve init executable: error finding executable "python app.py" in PATH [/usr/local/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin]: no such file or directory – EhanGreens Feb 03 '23 at 17:49
  • Did you chenge your `gcloud deploy` command as well? As mentioned the change to the `Dokerfile` is optional and not the source of the error – Matteo Zanoni Feb 04 '23 at 12:18
  • Hi Matteo, apologies, yes I also changed the gcloud command line as suggested (with the required image name and project ID) – EhanGreens Feb 04 '23 at 19:16
  • @EhanGreens Strange... Is the error still the same? – Matteo Zanoni Feb 05 '23 at 13:38
0

I have been able to successfully deploy to cloud run using the following, however when accessing the deployed API it returns a 404 error. Any suggestions will be appreciated.

I switch to Waitress (Waitress is meant to be a production-quality pure-Python WSGI server).

app.py

from flask import Flask, request
import subprocess

app = Flask(__name__)

@app.route("/run_script", methods=["GET", "POST"])
def run_script():
    result = subprocess.run(["python", "test.py"], capture_output=True)
    return result.stdout

if __name__ == "__main__":
    from waitress import serve
    serve(app, host='0.0.0.0', port=8080)

Dockerfile:

FROM python:3.9

WORKDIR /app

COPY . .

RUN pip install --no-cache-dir -r requirements.txt

CMD ["python", "app.py"]

test.py:

df_AS = db.collectionName
#convert entire collection to Pandas dataframe
df_AS = pd.DataFrame(list(df_AS.find()))


newCollection.insert_many(df_AS.to_dict("records"))

this successfully deployed however the end point is not included in the url and have to be manually inserted at the end of the url. is this normal?

EhanGreens
  • 11
  • 2