skip to Main Content

After trying almost all different solutions on the web I still have issues with hot reloading of a FAST api app inside a Docker container.

I can see that the volume mapping is doing it’s thing and the files are updated inside the docker container.

The console log tells me uvicorn is watching files inside the correct folder.
But any change i make is not triggering a reload of the app.

I have the following setup:

My docker compose:

#docker-compose.yml
version: "3"

services:
  app:
    container_name: api
    image: api:latest
    depends_on:
      - mysqldb
    build: 
      context: .
      dockerfile: Dockerfile.dev
      args:
        DEV: "true"
    ports:
      - "8080:8080"
    env_file:
      - .env
    environment:
      - WATCHFILES_FORCE_POLLING=true
      - DEV=1
      - MYSQL_HOSTNAME=mysqldb
      - MYSQL_PORT=3306
    command: uvicorn app.main:app --host 0.0.0.0 --port 8080 --reload --reload-dir /src/app
    volumes:
      - ./app:/src/app
  mysqldb:
    container_name: mysqldb
    image: mysql:latest
    restart: always
    ports:
     - 3307:3306
    environment:
      MYSQL_ROOT_PASSWORD: randompassword
      MYSQL_DATABASE: my-database

And my docker compose

#dockerfile.dev
FROM python:3.10-slim-buster

ENV PYTHONUNBUFFERED 1

COPY requirements.txt /
COPY alembic.ini /
COPY migrations /migrations

RUN pip install --upgrade pip setuptools wheel gunicorn uvloop httptools
RUN pip install -r requirements.txt
RUN pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
RUN pip install sentence-transformers 

# Copy the source code to src folder
COPY . /src

ENV PYTHONPATH=/src

EXPOSE 8080

# FOR local dev the startup happens inside the docker-compose with reload options
COPY startup.sh /src/startup.sh
RUN chmod +x /src/startup.sh

CMD ["uvicorn", "app.main:app","--host", "0.0.0.0", "--port", "8080", "--reload"]

I’ve tried almost all possible configurations of the reload.

  • Without running the uvicorn command inside the docker file
  • With the reload dir as root (/), app, and src/app
  • Without the reload dir
  • With the guvicorn server instead of the uvicorn server

So i’m kinda stuck.
Can anyone help me out?

2

Answers


  1. Chosen as BEST ANSWER

    After tinkering arround with different set ups we now have a stable reload workspace. The issue with the uvicorn --reload statement had to do with volume mapping and the point when the command got called.

    Now instead of running the uvicorn command from the docker compose file I run a command to keep the container alive:

    command: /bin/sh -c "while true; do sleep 30; done"
    

    Then I connect manually with the container:

    docker exec -it ml_api /bin/bash
    

    And then i can start (or manually restart) the uvicorn (or guvicorn) server. The reload statement now works correctly and if any big changes happen I can restart uvicorn without restarting my docker container.


  2. Your general approach should work, but you may be relying on PYTHONPATH erroneously, which in turn means Python does not see the mounted code.

    Per point 7 in the Docker docs, ENV in your Dockerfile is disabled by any environment in the docker-compose script. You could consider using WORKDIR in the Dockerfile, and if necessary working_dir in your compose file to achieve a similar result.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search