Docker image for Flask applicatno [duplicate] - python

This question already has answers here:
How can I change the host and port that the flask command uses?
(6 answers)
Closed last month.
when a run a simple flask application with a specified port(5888) from the console it is running well and is provided with a
URL: * Debugger PIN: 125-876-281
* Running on http://127.0.0.1:5888/ (Press CTRL+C to quit)
for the same application when I build a docker image and run using the comman : docker run -p 192.168.0.152:5888:5888 dock_test is is giving the
URL : *** Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://172.17.0.3:5000** with the different port(5000).
The main python file: app.py
from flask import Flask
app = Flask(__name__)
#app.route("/")
def index():
return "running"
if __name__ == "__main__":
app.run(debug=True,port=5888)
docker file: Dockerfile
FROM ubuntu
RUN apt update
RUN apt install python3-pip -y
RUN pip3 install Flask
COPY requirements.txt requirements.txt
ENV LISTEN_PORT=5888
EXPOSE 5888
RUN pip3 install -r requirements.txt
WORKDIR C:\Users\heman\PycharmProjects\dock_test\main.py
COPY . .
ENV FLASK_APP=main.py
CMD ["python3","-m","flask","run","--host=0.0.0.0"]
Step-1: To build the image I've run : docker build -t dock_test .(it created the docker image well)
step-2: To run : docker run -d -p 5888:5888 dock_test
output: * Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://172.17.0.3:5000
why the port is changing to 5000 instead of 5888?

I think you are missing the port number in the Dockerfile.
In your docker file, you are calling your application as a module (by using -m). When you run a module, it's first imported internally and then runs the function inside it. You can find more details here: Execution of Python code with -m option or not
So basically, the if "____main___" part is skipped when you call using the -m command. Thus, the flask app is defaulting to the default port 5000. If you specify it in the Dockerfile, as shown below, it should work.
CMD ["python3","-m", "flask", "run","--host=0.0.0.0", "--port=5888"]

Related

Refused to connect local ip address by using docker while running ok without docker [duplicate]

This question already has answers here:
Deploying a minimal flask app in docker - server connection issues
(8 answers)
Closed 7 months ago.
[Editted]
I am trying to dockerize a simple flask project. I kept getting this error when I run the project using docker. On the other hand the project works just fine when I run it normally using python3 test-flask.py
Docker File
FROM python:3.9.6-slim
# https://www.lifewithpython.com/2021/05/python-docker-env-vars.html
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PYTHONUTF8=1 \
PIP_DISABLE_PIP_VERSION_CHECK=on
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
curl \
wget \
unzip \
jq \
ffmpeg \
libsndfile1-dev \
&& rm -rf /var/lib/apt/lists/*
RUN wget "https://download.pytorch.org/whl/cpu/torch-1.10.2%2Bcpu-cp39-cp39-linux_x86_64.whl" \
&& pip install torch-1.10.2+cpu-cp39-cp39-linux_x86_64.whl
RUN mkdir app
WORKDIR /app
COPY README.md .
COPY requirements.txt .
COPY setup.py .
COPY src ./src
RUN pip install .
# COPY main.py .
COPY test_flask.py .
CMD [ "python", "test_flask.py", "run", "--host", "0.0.0.0"]
docker-compose.yml
version: '3.9'
services:
asr-cpu-local:
build:
context: ./
dockerfile: ./Dockerfile
volumes:
- ./data:/data
- ./models:/models
ports:
- 127.0.0.1:8000:8000
In the Terminal and Docker Container log, after I run it with docker, it shows no error at all
* Serving Flask app 'test_flask' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:8000 (Press CTRL+C to quit)
* Restarting with stat
For additional information, I have run docker port to check, but the error still occured:
docker port <container-name>
8000/tcp -> 127.0.0.1:8000
For the File test_flask.py:
from flask import Flask
app = Flask(__name__)
import librosa
from src.jrasr.predictors import Wav2vec2bert2bertPredictor
MODEL_CONFIG = {
"name": "Wav2vec2bert2bertPredictor",
"version": "0.0.1",
"models": [
{
"name": "wav2vec2",
"dir": "/models/wav2vec2-base-csj-kana-v0.0.1"
},
{
"name": "bert2bert",
"dir": "/models/bert2bert-csj-kana-v0.0.1"
}
]
}
#app.before_first_request
def load_model_to_app():
# Load the model
app.predictor = Wav2vec2bert2bertPredictor(MODEL_CONFIG)
#app.route('/')
def index():
return "This is Home Page"
#app.route('/data/<audio_path>')
def predict(audio_path):
model = app.predictor
audio_path = "/data/"+audio_path
data, _ = librosa.load(audio_path, sr=16000, mono=True, duration=10)
words = model.predict(data)
result = "".join(words)
return result
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000, debug=True)
But when I try to access the Ip address as shown in the Terminal and Docker Container Log, I got that 127.0.0.1 refuse to connect such as in the image shown below. The problem is in the terminal and docker log, there isn't any Error message, but still I can't access it, can anyone tell me, how to solve my problems?
Error at the local browser
127.0.0.1 is the localhost interface and when running inside the container only the container has access to it. To be accessible outside the container it should be the special IP 0.0.0.0 to bind all interfaces.
Solution 1
Change the host to be 0.0.0.0 instead of 127.0.0.1 in the test_flask.py. Something like the following snippet.
WARNING: As 0.0.0.0 binds all interfaces to the outside world it could be a security risk if running it locally instead of in a container. That said, the Solution 2 is the recommended one (With the 127.0.0.1 in the Python source as it is). So, when running it directly locally it binds to the localhost and when running it in the container it binds the outside world of the container itself.
...
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, debug=True)
Solution 2
On the other hand, to run it passing the host as an argument the Dockerfile should be changed to the following:
...
ENV FLASK_APP=test_flask
CMD ["flask", "run", "--host=0.0.0.0"]
Test it with the browser connecting to http://localhost:8000/ or http://127.0.0.1:8000/

DockerFile for a Python script with Firefox-based Selenium web driver, Flask & BS4 dependencies

Super new to python, and never used docker before. I want to host my python script on Google Cloud Run but need to package into a Docker container to submit to google.
What exactly needs to go in this DockerFile to upload to google?
Current info:
Python: v3.9.1
Flask: v1.1.2
Selenium Web Driver: v3.141.0
Firefox Geckodriver: v0.28.0
Beautifulsoup4: v4.9.3
Pandas: v1.2.0
Let me know if further information about the script is required.
I have found the following snippets of code to use as a starting point from here. I just don't know how to adjust to fit my specifications, nor do I know what 'gunicorn' is used for.
# Use the official Python image.
# https://hub.docker.com/_/python
FROM python:3.7
# Install manually all the missing libraries
RUN apt-get update
RUN apt-get install -y gconf-service libasound2 libatk1.0-0 libcairo2 libcups2 libfontconfig1 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libxss1 fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils
# Install Chrome
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN dpkg -i google-chrome-stable_current_amd64.deb; apt-get -fy install
# Install Python dependencies.
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . .
# 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.
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 main:app
# requirements.txt
Flask==1.0.2
gunicorn==19.9.0
selenium==3.141.0
chromedriver-binary==77.0.3865.40.0
Gunicorn is an application server for running your python application instance, it is a pure-Python HTTP server for WSGI applications. It allows you to run any Python application concurrently by running multiple Python processes within a single dyno.
Please have a look into the following Tutorial which explains in detail regarding gunicorn.
Regarding Cloud Run, to deploy to Cloud Run, please follow next steps or the Cloud Run Official Documentation:
1) Create a folder
2) In that folder, create a file named main.py and write your Flask code
Example of simple Flask code
import os
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello_world():
name = os.environ.get("NAME", "World")
return "Hello {}!".format(name)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
3) Now your app is finished and ready to be containerized and uploaded to Container Registry
3.1) So to containerize your app, you need a Dockerfile in the same directory as the source files (main.py)
3.2) Now build your container image using Cloud Build, run the following command from the directory containing the Dockerfile:
gcloud builds submit --tag gcr.io/PROJECT-ID/FOLDER_NAME
where PROJECT-ID is your GCP project ID. You can get it by running gcloud config get-value project
4) Finally you can deploy to Cloud Run by executing the following command:
gcloud run deploy --image gcr.io/PROJECT-ID/FOLDER_NAME --platform managed
You can also have a look into the Google Cloud Run Official GitHub Repository for a Cloud Run Hello World Sample.

Flask App not working when running on docker container

Im new to docker and Flask and I'm getting an issue when I try to run the app. The browser says the site (172.17.0.2:5000) can't be reached.
For anyone wondering, the Dockerfiles:
FROM ubuntu
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip3 install flask
RUN mkdir -p /opt/MyApp-test
COPY . /opt/MyApp-test
WORKDIR /opt/MyApp-test
EXPOSE 5000
ENTRYPOINT python3 main.py
CMD flask run --host 0.0.0.0
The main.py:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return 'IT WORKED! I AM RUNNING FROM A DOCKER CONTAINER!!!'
if __name__ == '__main__':
app.run()
And when I run the container, I get:
(base) daniellombardi#Daniels-MacBook-Pro MyApp-test % docker run 2625
* Serving Flask app "main" (lazy loading)
* 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 http://127.0.0.1:5000/ (Press CTRL+C to quit)
I try to go to http://127.0.0.1:5000/, unable to connect, then I inspect the container to get its IP address, and it says 172.0.1 instead of 127.0.0.1:5000, but also unable to connect. And the app works when I run it on my computer.
You should just bind the exposed port inside of your container to a port in docker host when calling docker run, thus docker run should be called this way:
docker run 2625 -p 5000:5000

How to run a scrapy spider in a flask app, from a docker container?

When running my flask app, which uses Python's subprocess to use scrapy within a flask app as specified here (How to integrate Flask & Scrapy?), from a Docker Container and calling the appropriate endpoints specified in my flask app, I receive the error message: ERR_EMPTY_RESPONSE. Executing the flask app outside of my docker container (python app.py, where app.py has my flask code), everything works as intended and my spiders are called using subprocess within the flask app.
Instead of using flask & subprocess to call my spiders within a web app, I tried using twisted & twisted-klein python libraries, with the same result when called from a docker Container. I have also created a new, clean scrapy project, meaning no specific code of my own, just the standard scrapy code and project structure upon creation. This resulted in the same error. I am not quite certain whether my approach is anti-pattern, since flask and scrapy are in bundled into run image, resulting in one container for two purposes.
Here is my server.py code. When executing outside a container (using python interpreter) everything works as intended.
When running it from a container, then I receive the error message (ERR_EMPTY_RESPONSE).
# server.py
import subprocess
from flask import Flask
from medien_crawler.spiders.firstclassspider import FirstClassSpider
app = Flask(__name__)
#app.route("/")
def return_hello():
return "Hello!"
#app.route("/firstclass")
def return_firstclass_comments():
spider_name = "firstclass"
response = subprocess.call(['scrapy', 'crawl', spider_name, '-a', 'start_url=https://someurl.com'])
return "OK!"
if __name__ == "__main__":
app.run(debug=True)
FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD [ "python", "./server.py" ]
Finally I run docker run -p 5000:5000 . It does not work. Any ideas?
Please try it.
.Dockerfile
FROM python:3.6
RUN apt-get update && apt-get install -y wget
WORKDIR /usr/src/app
ADD . /usr/src/app
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 5000
CMD [ "python", "./server.py" ]

python3: can't find '__main__' module in 'app.py'

I'm trying to create a Docker container to be able to create a GUI with Flask for the utilisation of a tensorflow model.
The thing is that I would like to be able to modify my python files in real time and not have to rebuild my container everytime.
So for now I've created 3 files :
requirement.txt
Flask
tensorflow
keras
Dockerfile
# Use an official Python runtime as a parent image
FROM python:3.5.6-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 --trusted-host pypi.python.org -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python3", "app.py"]
app.py
from flask import Flask
import os
import socket
app = Flask(__name__)
#app.route("/")
def test():
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
So after all this I build my container with this command
docker build -t modelgui .
End then I use this command to run my container and make a link between the app file I want to modify on the host and the one in the container
docker run -p 4000:80 -v /home/Documents/modelGUI:/app modelgui
But I get this error and I really don't know why
/usr/local/bin/python3: can't find '__main__' module in 'app.py'
My problem might be dumb to resolve but I'm really stuck here.
Check that /home/Documents/modelGUI in your bind volume mount is the path to where your code files reside and that app.py in that path is not created as a directory rather than a python file with the code you intend to run.
If app.py in /home/Documents/modelGUI is a dir, then the cause of this problem is that are not calling your script app.py at all, you are just giving the Python interpreter a nonexistent script name, which in case a similarly named directory (case-insensitive actually) exists it tries to execute it.
I've tried to replicate:
$ ls -lFs
Dockerfile
app.py/
requirements.txt
Then called the Python interpreter with app.py:
$ python3 app.py
/usr/local/bin/python3: can't find '__main__' module in 'app.py'
Running this locally, it looks like mounting your volume is overwriting your directory:
No volume
docker run -it test_image bash
root#c3870b9845c3:/app# ls
Dockerfile app.py requirements.txt
root#c3870b9845c3:/app# python app.py
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
With volume
docker run -it -v ~/Barings_VSTS/modelGUI:/app test_image bash
root#f6349f899079:/app# ls
somefile.txt
root#f6349f899079:/app#
That could be part of the issue. If you want to mount a filesystem in, I would mount it into a different directory. The default volume behavior is such that whatever you copied into app will be overwritten by the contents of modelGUI

Categories