Docker exit code 0 issue - python

Here is my logs after trying to dockerizing a fastapi script:
$ docker-compose logs -f
Attaching to docker-name
docker-name exited with code 0
Here is my docker compose file:
version: '3'
services:
observatory-service:
build: ./observatory
volumes:
- ./observatory:/usr/src/app
ports:
- 8000:8000
docker file:
FROM python:3.9
COPY requirements.txt /usr/src/app/
RUN pip install -r /usr/src/app/requirements.txt
COPY . /usr/src/app
CMD ["python", "/usr/src/app/api.py"]
api.py:
from fastapi import FastAPI
app = FastAPI()
#app.get("/")
def read_root():
return { "Lux app": "Welcome to Lux app" }
#app.post("/extract_text")
def ali():
return {"Hello": "World"}
I am sure it goes through api.py but it exits out of it without error. I am running this on Windows docker.

The problem is that you're directly calling the fastAPI server script with python and not wrapped with a ASGI web server such as Uvicorn. This is explained in the debugging page of fastAPI.
I tested with latest versions of fastapi/uvicorn and it works just fine. I suggest you make these two changes:
1 - Add this line to your requirements.txt file:
uvicorn
2- Then add the first line and the two last lines to the end of your api.py file:
import uvicorn
from fastapi import FastAPI
app = FastAPI()
#app.get("/")
def read_root():
return { "Lux app": "Welcome to Lux app" }
#app.post("/extract_text")
def ali():
return {"Hello": "World"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
Result of GET /
{"Lux app":"Welcome to Lux app"}
Finally, another alternative would be following the docker guide provided by fastAPI which solves this easily by calling your fastapi module directly with uvicorn. This will achieve the same as above.
Example of Dockerfile:
FROM python:3.9
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]

Related

Deploying Flask API to 'cloud run' result in error using gcloud run deploy

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:
docker build -t .
docker tag gcr.io//
docker push gcr.io//
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
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
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?

Docker container cant run pygame

so actually, i want to run a pygame application using docker container. however, when i run the docker and click the link at the terminal, it opens a tab and it says : "The webpage at http://0.0.0.0:8000/ might be temporarily down or it may have moved permanently to a new web address."
here's the aliens.py github link: https://github.com/xamox/pygame/blob/master/examples/aliens.py
in the aliens.py file, I added some code into it:
from fastapi import FastAPI
import uvicorn
app = FastAPI()
and
if __name__ == '__main__': uvicorn.run(app, port=8000, host="0.0.0.0")
and for the code of the Dockerfile file that I have created:
Python FROM:3.10
WORKDIR /fastapi-app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY ./app ./app
CMD["python", "./app/aliens.py"]
Is the problem is in the IP address of the host?
Dockerfile
# python FROM:3.10 <----
FROM python:3.10
WORKDIR /fastapi-app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY ./app ./app
#CMD["python", "./app/aliens.py"]
# ^ whitespace missing
CMD ["python", "./app/aliens.py"]
aliens.py
from fastapi import FastAPI
import uvicorn
app = FastAPI()
if __name__ == '__main__':
uvicorn.run(app, port=8000, host="0.0.0.0")
Testing without aliens-code
# build
$ docker build -t my-app .
# run
$ docker run -d -rm --name mayapp -p 80:8000 my-app
# 80 host-port
# 8000 container-port
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
5ba7b461e92e my-app "python ./app/aliens…" 3 seconds ago Up 1 second 0.0.0.0:80->8000/tcp mayapp
http://localhost/docs

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.

http://localhost/5000 not working in docker flask

can't open file '/web/manage.py': [Errno 2] No such file or directory
exited with code 2
NOTE: Tried all similar problems solution posted, did not work.
No matter what I do, not able to get http://localhost/5000 to work. Even if the above error goes away by removing volume and command from docker-container.
Below is docker-compose.yml
services:
web:
build: ./web
command: python /web/manage.py runserver 0.0.0.0:8000
volumes:
- './users:/usr/src/app'
ports:
- 5000:5000
env_file:
- ./.env.dev
Below is Dockerfile:
# pull official base image
FROM python:3.9.5-slim-buster
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt
# copy project
COPY . /usr/src/app/
BELOW IS manage.py:
from flask.cli import FlaskGroup
from project import app
cli = FlaskGroup(app)
if __name__ == "__main__":
cli()
BELOW IS init.py:
from flask import Flask, jsonify
app = Flask(__name__)
#app.route("/")
def hello_world():
return jsonify(hello="world")
Below is the structure:
The ones marked in red appeared when I ran this command: docker-compose build
enter image description here
A couple of changes to do.
The cli command in your docker-compose.yml file needs to be:
command: python /usr/src/app/manage.py run -h 0.0.0.0 -p 8000
There the command name is run and not runserver. Also the host ip to bind and port to listen are configured as different command options.
Also the configured port mapping for the service needs to map to the container port from the command:
ports:
- 5000:8000
In your manage.py module, FlaskGroup should be provided create_app option which is factory not the app instance.
You can implement this as a lambda function.
cli = FlaskGroup(create_app=(lambda:app))
Edit
The source files are not mounted in the container volume that why you're getting "no such file manage.py".
You need to mount your source files in the container volume under /usr/src/app.
volumes:
- './web:/usr/src/app'

Why can't my two docker containers communicate?

I have two docker containers running Flask, just a simple backend/frontend example bit I was running through to learn docker and flask.
My frontend is:
from flask import Flask, jsonify
import requests
import simplejson
import json
app = Flask(__name__)
#app.route('/')
def hello():
uri = "http://127.0.0.1:5000/tasks"
try:
uResponse = requests.get(uri)
except requests.ConnectionError:
return "Connection Error"
Jresponse = uResponse.text
data = json.loads(Jresponse)
fullString = ""
title = data['tasks'][0]['title']
description = data['tasks'][0]['description']
fullString += title
fullString += "<br/>"
fullString += description
return fullString
if __name__ == '__main__':
app.run(debug=True,host="0.0.0.0", port=2000)
This works fine when I run it locally, and it also works when I run it in my docker. I'm able to go to the frontend at localhost:2000 and I see valid data.
My backend code is:
from flask import Flask,request, jsonify, make_response
from flask import abort
import csv
import json
import flask
app = Flask(__name__)
tasks = [
{
'id': 1,
'title': u'example title 1',
'description': u'example description 1',
'done': False
},
{
'id': 2,
'title': u'example title 2',
'description': u'example description 2',
'done': False
}
]
#app.route('/tasks', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})
if __name__ == '__main__':
app.run(debug=True,host="0.0.0.0", port=5000)
If I run both of these without docker, and I go to the frontend at localhost:2000 I get what I expect, the 0th entry of tasks description and title.
When I run these in docker, everything seems to work, but I get the Connection Error from the frontend. So, the requests.get(uri) seems to not be working once dockerized.
Here's my docker files
For Backend
FROM ubuntu:latest
MAINTAINER me
RUN apt-get update -y
RUN apt-get install -y python3-pip python3-dev build-essential
COPY . /app
WORKDIR /app
RUN pip3 install -r requirements.txt
ENTRYPOINT ["python3"]
CMD ["backend.py"]
For Frontend
FROM ubuntu:latest
MAINTAINER me
RUN apt-get update -y
RUN apt-get install -y python3-pip python3-dev build-essential
COPY . /app
WORKDIR /app
ENV FLASK_APP=/app/frontend.py
ENV FLASK_ENV=development
RUN pip3 install -r requirements.txt
ENTRYPOINT ["python3"]
CMD ["frontend.py"]
So, it appears they both work individually, but can't communicate. Why is that? As if it isn't obvious, I'm new to docker.
EDIT1
Command for frontend:
sudo docker run -d -p 2000:2000 frontend
Command for backend:
sudo docker run -d -p 5000:5000 backend
EDIT2
I moved this to docker compose, and have the same issue it appears.
docker-compose.yml
version: '3'
services:
backend:
build:
context: backend/
dockerfile: compose/lib/backend/Dockerfile
ports:
- "5000:5000"
frontend:
build:
context: lib/frontend/
dockerfile: compose/lib/frontend/Dockerfile
ports:
- "2000:2000"
No changes to Docker files. According to the docs here it is correct that I don't need specific networking, and there is a default network created. However, this still works fine under just flask, but I can't get them to attach using docker or docker-compose.
Can you share the docker run command you're using?
Are you exposing the ports with the -p flag?
docker run -p 5000:5000 ...
[Update]: Depending on your docker install and config, you may not be able to use that IP. Docker considers the 127.0.0.1 IP to mean "this container," not "this machine."
A bridged network may address this, but I'd recommend using docker-compose instead (details below).
If, for the purposes of this experiment, you are planning on running these two containers at the same time on the same machine always, you might want to look into docker-compose, which lets you run multiple containers from the same master command, and gives you nice bonus features like creating a virtual network for the two to connect to each other on, without external networks being able to access them. e.g. your data server can be visible only to your other flask container, but that one can be publicly exposed on your host machine's network interface.
In the case of docker-compose, you can use the following (untested) docker-compose.yml as a start:
version: 3
services:
backend:
build: path/to/dockerfile
ports:
- 5000:5000
frontend:
build: path/to/dockerfile
ports:
- 2000:2000

Categories

Resources