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