I am attempting to run a Flask server in a docker container with debug enabled so that I can hot reload during development and try out changes. Unfortunately the hot reload is not detecting changes even though I have verified the file has changed from within the container. My set up is as follows:
Host directory structure
|
|- Src
| |- app.py
|
|- docker-compose.yaml
|- Dockerfile
|- requirements.txt
Requirements.txt
flask
Dockerfile
FROM python:3.11-slim
ENV DEBUG_COLOR=true
ENV PYTHONPATH=.
RUN mkdir /usr/local/app
WORKDIR /usr/local/app
COPY requirements.txt /usr/local/app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
docker-compose.yaml
services:
test:
build:
dockerfile: ./Dockerfile
context: .
image: test:latest
environment:
- FLASK_DEBUG=1
ports: ['3000:3000']
volumes: [
'./src:/usr/local/app'
]
command:
python app.py
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
print('GET /, was called.')
return 'Hello world.'
if __name__ == "__main__":
app.run(host = '0.0.0.0', port = '3000')
I can kick this off from the command line using docker compose up
and everything builds and runs as expected resulting in the output:
Attaching to test-1
test-1 | * Serving Flask app 'app'
test-1 | * Debug mode: on
test-1 | WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
test-1 | * Running on all addresses (0.0.0.0)
test-1 | * Running on http://127.0.0.1:3000
test-1 | * Running on http://172.18.0.2:3000
test-1 | Press CTRL+C to quit
test-1 | * Restarting with stat
test-1 | * Debugger is active!
test-1 | * Debugger PIN: 582-087-710
From this I can see the debugger is running and it should be restarting with stat. I can then visit the served page at http://127.0.0.1:3000 and it serves the expected Hello world!
. I can also attach to the running container and check the content of app.py
using cat app.py
.
If I then fire up an editor on the host and change the content of app.py
, for example change the message returned to be:
return 'Hello test world.'
I expect the debugger to detect the change and reload, however it does not do this. I can look at the content of app.py
in the container I can see the code has changed, but visiting the URL I still get served Hello world!
.
Note: this is unlike the issue in Auto reloading flask server on Docker where the code was copied into the container and volumes
was not used to map the host src to the container directory.
Any suggestions on the step I am missing here are very welcome!
Based on your example, I changed the mounted path from /usr/local/app
to /project
, and set debug=True
. Flask was then able to detect changes and hot-reload properly again.
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
print('GET /, was called.')
return 'Hello world.'
if __name__ == "__main__":
app.run(host = '0.0.0.0', port = '3000', debug=True)
Dockerfile
FROM python:3.11-slim
ENV DEBUG_COLOR=true
ENV PYTHONPATH=.
#RUN mkdir /usr/local/app
WORKDIR /project
COPY requirements.txt /project
RUN pip install -r requirements.txt
# Declare it on either the `docker-compose.yml` or `Dockerfile`, don't need both.
# CMD ["python", "app.py"]
docker-compose.yml
services:
test:
build:
dockerfile: ./Dockerfile
context: .
image: test:latest
# Because it's not using command like `flask run` to launch the project, so it's not necessary either.
#environment:
# - FLASK_DEBUG=1
ports: ['3000:3000']
volumes: [
'./src:/project'
]
command:
python app.py
After modifying above, rebuild and launch the project.
$ docker compose up --build
It’s quite strange. Despite setting debug=True
or using docker compose --watch
, hot-reloading still doesn’t work unless I change the mounted path from /usr/local/app
to /project
(which might be related to the system path or Flask's watchdog detection paths).
The /usr/local
directory is often used for system-level installations, and file system events might not be properly propagated when mounting volumes there in a Docker container.