I’m setting up a fastapi compose.yaml file for development.
Here the simplified layout of my project:
Dockerfile -> size optimized: 170MB
# The builder image, used to build the virtual environment
FROM python:3.11-bullseye as builder
# Install package manager
RUN pip install poetry==1.7.1
# Define environment
ENV POETRY_NO_INTERACTION=1
POETRY_VIRTUALENVS_IN_PROJECT=1
POETRY_VIRTUALENVS_CREATE=1
POETRY_CACHE_DIR=/tmp/poetry_cache
# Set work directory
WORKDIR /app
# Copy project dependencies
COPY pyproject.toml poetry.lock ./
# Install production dependencies only and remove poetry cache directory
RUN poetry install --without dev --no-root && rm -rf $POETRY_CACHE_DIR
# The runtime image, used to run the service
FROM python:3.11-slim-bullseye as runtime
# Set virtual environment path and add it to the system Path
ENV VIRTUAL_ENV=/app/.venv
PATH="/app/.venv/bin:$PATH"
# Copy project dependencies from builder stage
COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}
# Copy project code
COPY app/ /app/
# Run service
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
The layout generated in the debian container is the same, so everything is okay, when I run the container it deploys a fastapi server that works perfect!
I want to create a development environment that watch my code and reloads the server in every change.
For that I created the following compose.yaml:
services:
api:
image: pws
build:
context: .
dockerfile: Dockerfile
restart: on-failure
ports:
- "80:80"
volumes:
# - ./app/:/app # I have tried many combinations of this line
- ./app/:/app/
command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--reload"]
The issue is that running "docker compose up" goes well when "volumes" are not specified, but at the moment I try to include it, breaks:
Error:
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "uvicorn": executable file not found in $PATH: unknown
2
Answers
I have found a workarround using docker compose watch, but still curious about what is happening with bind mounts using "volumes"
On the host you have
.venv
in your root directory, but in your Dockerfile it’sapp/.venv
, so when you mountapp
from host there is no.venv
in the containerTo resolve it in your Dockerfile you should move
.venv
to/.venv
(or anywhere outside of/app
) from/app/.venv