I recently created an app using flask and put the py file in a docker container. However I am confused with online cases where people assigned the port.
First of all on the bottom of my py file I wrote
if __name__ == "__main__":
app.run(host='0.0.0.0',port=8000, debug=True)
In some cases I saw people specify the port in CMD when making dockerfile
CMD ["python3", "app.py", "--host=0.0.0.0", "--port=8000"]
In my own experience, the port assigned in CMD didn't work on my case at all. I wish to learn the differences between the two approaches and when to use each way.
Regarding this approach:
if __name__ == "__main__":
app.run(host='0.0.0.0',port=8000, debug=True)
__name__
is equal to "__main__"
when the app is launched directly with the python
interpreter (executed with the command python app.py
) - which is a python technicallity and nothing to do with Flask. In that case the app.run
function is called, and it accepts the various arguments as stated. app.run
causes the Werkzeug development server to run.
This block will not be run, if you're executing the program with a production WSGI server like gunicorn
as __name__
will not be equal to "__main__"
in that case, so the app.run
call is bypassed.
In practice, putting the app.run
call in this if
block means you can run the dev server with python app.py
and avoid running the dev server when the same code is imported by gunicorn
or similar in production.
There are lots of older tutorials or posts which reference the above approach. Modern versions of Flask ship with the flask
command which is intended to replace this. So essentially without that if
block, you can launch the development server which imports your app object in a similar manner to to gunicorn
:
flask run -h 0.0.0.0 -p 8000
This automatically looks for an object called app
in app.py
, and accepts the host and port options, as you can see from flask run --help
:
Options:
-h, --host TEXT The interface to bind to.
-p, --port INTEGER The port to bind to.
One advantage of this method is that the development server won't crash if you're using the auto reloader and introduce syntax errors. And of course the same code will be compatible with a production server like gunicorn
.
With the above in mind, regarding the command you pass:
python app.py --host=0.0.0.0 --port=8000
I'm not sure if you've been confused with references to the flask
command's supported options, but for this one to work you'd need to manually write some code to do something with those options. This could be done with a python module like argparse
, but that would probably be redundant given that the flask
command actually supports this out of the box.
To conclude: you should probably remove the if
block, and your Dockerfile should contain:
CMD ["flask", "run", "--host=0.0.0.0", "--port=8000"]
You may also wish to check the FLASK_ENV
environment variable is set to development
to use the auto reloader, and be aware that the CMD
line would need to be changed within this Dockerfile to run with gunicorn
or similar in production, but that's probably outwith the scope of this question.