I want my flask server to detect changes in code and reload automatically.
I'm running this on docker container.
Whenever I change something, I have to build and up again the container. I have no idea where's wrong. This is my first time using flask.
Here's my tree
├── docker-compose.yml
└── web
├── Dockerfile
├── app.py
├── crawler.py
└── requirements.txt
and code(app.py)
from flask import Flask
import requests
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello Flask!!'
if __name__ == '__main__':
app.run(debug = True, host = '0.0.0.0')
and docker-compose
version: '2'
services:
web:
build: ./web
ports:
- "5000:5000"
volumes:
- ./web:/code
Please give me some advice. Thank you in advance.
Flask supports code reload when in debug mode as you've already done. The problem is that the application is running on a container and this isolates it from the real source code you are developing. Anyway, you can share the source between the running container and the host with volumes on your docker-compose.yaml like this:
Here is the docker-compose.yaml
version: "3"
services:
web:
build: ./web
ports: ['5000:5000']
volumes: ['./web:/app']
And here the Dockerfile:
FROM python:alpine
EXPOSE 5000
WORKDIR app
COPY * /app/
RUN pip install -r requirements.txt
CMD python app.py
I managed to achieve flask auto reload in docker using docker-compose with the following config:
version: "3"
services:
web:
build: ./web
entrypoint:
- flask
- run
- --host=0.0.0.0
environment:
FLASK_DEBUG: 1
FLASK_APP: ./app.py
ports: ['5000:5000']
volumes: ['./web:/app']
You have to manually specify environment variables and entrypoint in the docker compose file in order to achieve auto reload.
Assuming your file structure is the below:
Dockerfile: (note WORKING DIR)
FROM python:3.6.5-slim
RUN mkdir -p /home/project/bottle
WORKDIR /home/project/bottle
COPY requirements.txt .
RUN pip install --upgrade pip --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
Docker Compose:
version: '3'
services:
web:
container_name: web
volumes:
- './web:/home/project/bottle/' <== Local Folder:WORKDIR
build: ./web
ports:
- "8080:8080"
This is my example:
version: "3.8"
services:
local-development:
build:
context: .
dockerfile: Dockerfiles/development.Dockerfile
ports:
- "5000:5000"
volumes:
- .:/code
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return "hello world"
if __name__ in "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)
debug=True enables Flask to change as your code changes.
Docker already plugs into your fs events to change the code "in the container".
If the compose is running different services (app and rq, for instance) you need to set up the volumes on both, or it won't work.
Related
I'm trying to dockerize a Python-Flask application, using also volumes in order to have a live update when I change the code, but volumes don't work and I have to stop the containers and open run it again.
That is the code that I try to change (main.py):
from flask import Flask
import pandas as pd
import json
import os
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello"
My dockerfile.dev:
FROM python:3.9.5-slim-buster
WORKDIR '/app'
COPY requirements.txt .
RUN pip3 install -r requirements.txt
RUN pip install python-dotenv
COPY ./ ./
ENV FLASK_APP=main.py
EXPOSE 5000
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
My docker-compose.yaml
version: "3"
services:
backend:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "5000:5000"
expose:
- "5000"
volumes:
- .:/app
stdin_open: true
environment:
- CHOKIDAR_USEPOLLING=true
- PGHOST=db
- PGUSER=userp
- PGDATABASE=p
- PGPASSWORD=pgpwd
- PGPORT=5432
- DB_HOST=db
- POSTGRES_DB=p
- POSTGRES_USER=userp
- POSTGRES_PASSWORD=pgpwd
depends_on:
- db
db:
image: postgres:latest
restart: always
environment:
- POSTGRES_DB=db
- DB_HOST=127.0.0.1
- POSTGRES_USER=userp
- POSTGRES_PASSWORD=pgpwd
- POSTGRES_ROOT_PASSWORD=pgpwd
volumes:
- db-data-p:/var/lib/postgresql/data
pgadmin-p:
container_name: pgadmin4_container_p
image: dpage/pgadmin4
restart: always
environment:
PGADMIN_DEFAULT_EMAIL: admin#admin.com
PGADMIN_DEFAULT_PASSWORD: root
ports:
- "5050:80"
logging:
driver: none
volumes:
db-data-p:
To start I execute docker-compose up
Volume /app seems not works
Flask does not reload files by default. You need to enable that explicitly e.g. by passing --debug on the flask command line:
python3 -m flask --debug run --host=0.0.0.0
If you modify your Dockerfile to use the --debug flag...
CMD [ "python3", "-m" , "flask", "--debug", "run", "--host=0.0.0.0"]
...then it will work as you expect. You could also set the FLASK_DEBUG environment variable instead of using the --debug flag:
services:
backend:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "5000:5000"
volumes:
- .:/app
environment:
- FLASK_DEBUG=1
I'm doing a practice application to learn docker, I'm doing the application with Python and fast Api along with its tutorial, I'm using everything with dockerfile and docker compose, which has a connection to the postgresql database, for that I'm using a orm sqlalchemy, running my application 'normally' from the command line, the project runs without any problem, but when running it with docker compose it generates several errors like the following:
ModuleNotFoundError: No module named 'routers'
When I 'solve' it, it generates another error which I have not been able to solve and I do not understand which is the following:
ModuleNotFoundError: No module named 'sqlalchemy'
Well, if I have sqlalchemy install, requirements.txt:
SQLAlchemy==1.4.39
This is my Python code, this is the main one:
from fastapi import FastAPI
from .routers import roles
app = FastAPI()
app.include_router(roles.router)
And this is the code where the error is generated:
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from db.postgres_connection import SessionLocal, engine
from models import roles
from schemas import roles as schemas
roles.Base.metadata.create_all(bind=engine)
router = APIRouter()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
#router.get('/api/v1/roles/', response_model=list[schemas.RoleBase])
async def get_roles(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
roles = get_roles(db, skip=skip, limit=limit)
return roles
This is my Dockerfile:
FROM python:3.10.5-slim-buster
WORKDIR /code
COPY ./app ./code/app
COPY ./requirements.txt /code/
RUN pip install -r requirements.txt
EXPOSE 8000
CMD [ "uvicorn", "app.main:app", "--reload" ]
This is my docker compose file:
version: '3.9'
services:
web:
build: .
ports:
- '8000:8000'
volumes:
- .:/app
db:
image: postgres
restart: always
environment:
POSTGRES_USER: hamel
POSTGRES_PASSWORD: contrasena
POSTGRES_DB: bankmel
volumes:
- /home/isla/storage:/var/lib/postgresql/data
ports:
- '5432:5432'
structure folder:
you got a couple of problems
In the docker file change, your copy path code is creating one more directory under code.
COPY ./app ./app
then you will have a couple of other problems in your code.
Modify your Dockerfile as follows, I'm sure this error will be fixed:
FROM python:3.10.5-slim-buster
WORKDIR /code
COPY ./app ./app
COPY ./requirements.txt ./requirements.txt
RUN pip install -r requirements.txt
EXPOSE 8000
CMD [ "uvicorn", "app.main:app", "--reload" ]
also in docker-compose.yml you should change volume in web as follows:
volumes:
- .:/code
I am using a docker-compose Flask implementation with the following configuration
docker-compose:
version: '3'
services:
dashboard:
build:
context: dashboard/
args:
APP_PORT: "8080"
container_name: dashboard
ports:
- "8080:8080"
restart: unless-stopped
environment:
APP_ENV: "prod"
APP_DEBUG: "False"
APP_PORT: "8080"
volumes:
- ./dashboard/:/usr/src/app
dashboard/Dockerfile:
FROM python:3.7-slim-bullseye
ENV PYTHONUNBUFFERED True
ARG APP_PORT
ENV APP_HOME /usr/src/app
WORKDIR $APP_HOME
COPY requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
CMD exec gunicorn --bind :$APP_PORT --workers 1 --threads 8 --timeout 0 main:app
dashboard/main.py:
import os
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
If I apply any change to the index.html file in my host system using VSCode, these changes won't apply when I refresh the page. However, I have tried getting into the container with docker exec -it dashboard bash and cat /usr/src/app/templates/index.html and they are reflected inside the container, since the volume is shared between the host and the container.
If I stop the container and run it again the changes are applied, but as I am working on frontend doing that all the time is pretty annoying.
Why the changes won't show on the browser but they are replicated on the container?
You should use: TEMPLATES_AUTO_RELOAD=True
From https://flask.palletsprojects.com/en/2.0.x/config/
It appears that the templates are preloaded and won't update until you enable this feature.
i am trying to connect & build two docker file with docker-compose. I am new to docker & then its getting confused while connecting with docker-compose.
Main purpose: connecting frontend & backend (of flask application) via docker-compose.
If my Dockerfile & docker-compose.yml file wrong. please correct me
like front end in one frontend folder with Dockerfile.
back end in another folder with Dockerfile. (connecting this 2, via doc-comp)
here's my file structure (inside template folder - loginpage.html)
app.py
from flask import Flask, render_template, flash, redirect, url_for, session, logging, request
app = Flask(__name__)
app.secret_key = 'hello'
#app.route("/", methods=["GET", "POST"])
def login():
if request.method == "POST":
uname = request.form["uname"]
return render_template("loginpage.html", uname=uname)
else:
return render_template("loginpage.html")
if __name__ == "__main__":
app.run(debug=True, port=5048,host='0.0.0.0')
backend/Dockerfile
FROM python:3.7-slim
ADD ./requirements.txt /backend/requirements.txt
WORKDIR /backend
RUN pip install -r requirements.txt
ADD . /backend
ENTRYPOINT ["python"]
CMD ["/backend/app.py"]
EXPOSE 5048
frontend/Dockerfile
FROM python:3.7-slim
COPY templates /backend/
COPY . /backend
WORKDIR /backend
docker-compose.yml
version: '2'
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
restart: always
ports:
- "5048:5048"
frontend:
build: ./frontend
you can write docker-compose file something like this ..
version: "3.7"
services:
frontend:
build:
context: ./frontEnd
container_name: frontend
depends_on: [backend]
ports:
- "5000:5000"
networks:
- my_own_network
links:
- "backend:backend"
backend:
build:
context: ./backend
container_name: backend
ports:
- "5048:5048"
networks:
- my_own_network
networks:
my_own_network:
I have been investigating related questions but could not find a correct solution to this issue. All of my routes work locally. However, when I run docker-compose up to containerize my app, my app will start but all routes except for the root "hello world" route returns a 404 error.
I've attempted setting "SERVER_NAME" in app.config and appending an extra "/" on my route urls like other posts have suggested but to no avail.
Any suggestions on how to fix this?
app/app.py
#app.route("/") # <-- this route works
def hello_world():
return "Hello, world!"
#app.route("/test", methods=["POST"]) # <-- this one doesn't
def test():
return "Test POST route"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Dockerfile:
FROM tiangolo/uwsgi-nginx-flask:python3.6
COPY requirements.txt /
WORKDIR /
RUN pip install -r ./requirements.txt --no-cache-dir
COPY app/ /app/
WORKDIR /app
ENV FLASK_APP=app.py
ENV FLASK_ENV=production
CMD flask db upgrade && python app.py
docker-compose.yml
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
env_file:
- .env
You need to mount the source code folder in the docker compose rather than the dockerfile, otherwise you need to rebuild the image every time the code changes. In docker compose you can use volumes property to do this. You can read more here https://docs.docker.com/compose/compose-file/
Example
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
env_file:
- .env
volumes:
- ./app:/app