trying to dockerize this flask app… running the following
docker build --tag flask-website .
works, output successfully built, successfully tagged.
edit: the next command works
$ docker run --publish 5000:5000 flask-website * 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
ok, so then I run curl localhost:5000
which gives this error
curl: (7) Failed to connect to localhost port 5000: Connection refused
ok straight forward enough, so then I try this
docker-compose up
and this results
Creating network "app_default" with the default driver Creating app_web_1 ... done Attaching to app_web_1 web_1 | * Environment: production web_1 | WARNING: This is a development server. Do not use it in a production deployment. web_1 | Use a production WSGI server instead. web_1 | * Debug mode: off
however trying to navigate to localhost:5000 I get
This site can’t be reachedThe webpage at http://localhost:5000/ might be temporarily down or it may have moved permanently to a new web address. ERR_SOCKET_NOT_CONNECTED
directory structure looks like this
├──app_folder/ └── app/ | ├── static/ | | └── css/ | | └──app.css | | └── js/ | | └──app.js | └── templates/ | | └── app.html | | └── subapp.html | | └── subapp1.html | | └── subapp2.html | | └── subapp3.html | └── app.py | └── util.py | └── pickle_file.pickle | └── requirements.txt | └── Dockerfile | └── Makefile | └── docker-compose.yml
dockerfile looks like this
FROM python:3.8 ENV PYTHONUNBUFFERED=1 WORKDIR / COPY requirements.txt requirements.txt COPY . . RUN pip install -r requirements.txt # EXPOSE 5000 CMD [ "python", "-m" , "flask", "run", "--host=0.0.0.0"]
I had tried with EXPOSE 5000 uncommented and commented, making no difference
I also updated the directory structure and dockerfile, which got rid of the command line error I was seeing
docker-compose looks like this
version: "3.7" services: web: image: flask-website:latest ports: - 5000:5000
I tried with the dockerfile, docker-compose, makefile, and requirements outside of the app directory and a slightly modified dockerfile on the WORKDIR line, that resulted in this error
Error: Failed to find Flask application or factory in module "app". Use "FLASK_APP=app:name to specify one.
not sure what else to try? I can run it locally with python -m flask run
, but I cannot seem to dockerize it, seems like this should not be this difficult?
for completeness sake, app.py looks like this
from flask import Flask, request, jsonify from flask import render_template, redirect import json import util app = Flask(__name__, template_folder="templates", static_folder="static") @app.route("/", methods=["GET", "POST"]) def index(): return render_template("app.html") @app.route("/predict_home_price", methods=["GET", "POST"]) def make_prediction(): x = request.form["x"] y = float(request.form["y"] response = jsonify( { "prediction": util.prediction(x, y) } ) response.headers.add("Access-Control-Allow-Origin", "*") return response if __name__ == "__main__": from waitress import serve serve(app, host="0.0.0.0", port=5000)
util.py looks like this
import pickle import pandas as pd from scipy.special import inv_boxcox # to run locally uncomment out the following # with open("/path/to/pickle/app/pickle_mod.pickle", "rb") as f: # to run in docker use the following with open("app/pickle_mod.pickle", "rb") as f: __model = pickle.load(f) def prediction(x, y): lambs = 0.205 a = [[x, y]] cols = ["x", "y"] my_data = pd.DataFrame(data=a, columns=cols) pred = inv_boxcox(__model.predict(my_data)[0], lambs) return f"${round(pred)}" if __name__ == "__main__": print(prediction(5, 4))
I have also tried both ways with the pickle import in util, same result – I thought because I was building it in a docker container that the second import was correct
I have also tried this block for app.run as well with the same result
if __name__ == "__main__": app.run()
Advertisement
Answer
ok the following changes were required to get this image to build and the container to run
dockerfile:
FROM python:3.8 WORKDIR / COPY requirements.txt requirements.txt RUN pip install -r requirements.txt COPY . . EXPOSE 5000 ENTRYPOINT ["python", "./app.py"]
then the following change to the main application app.py
if __name__ == "__main__": app.run(debug=True, host='0.0.0.0')
then to util.py, which had an error I did not see until running docker run [TAG]
with open("pickle_mod.pickle", "rb") as f: __model = pickle.load(f)
then run docker build -t [TAG] .
then run docker-compose up
then navigate to localhost listening on port 5000 and there is the running container