diff --git a/Dockerfile b/Dockerfile index 35c3d16..615247b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,9 @@ ENV UV_COMPILE_BYTECODE=1 # Copy from the cache instead of linking since it's a mounted volume ENV UV_LINK_MODE=copy +# Omit development dependencies +ENV UV_NO_DEV=1 + # Ensure installed tools can be executed out of the box ENV UV_TOOL_BIN_DIR=/usr/local/bin @@ -21,13 +24,13 @@ ENV UV_TOOL_BIN_DIR=/usr/local/bin RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --locked --no-install-project --no-dev + uv sync --locked --no-install-project # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching COPY . /app RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --locked --no-dev + uv sync --locked # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" @@ -39,7 +42,8 @@ ENTRYPOINT [] USER nonroot # Run the FastAPI application by default +# Uses `uv run` to sync dependencies on startup, respecting UV_NO_DEV # Uses `fastapi dev` to enable hot-reloading when the `watch` sync occurs # Uses `--host 0.0.0.0` to allow access from outside the container # Note in production, you should use `fastapi run` instead -CMD ["fastapi", "dev", "--host", "0.0.0.0", "src/uv_docker_example"] +CMD ["uv", "run", "fastapi", "dev", "--host", "0.0.0.0", "src/uv_docker_example"] diff --git a/compose.yml b/compose.yml index 8289df3..4aade91 100644 --- a/compose.yml +++ b/compose.yml @@ -7,6 +7,10 @@ services: ports: - "8000:8000" + # Include development dependencies when working locally + environment: + - UV_NO_DEV=0 + develop: # Create a `watch` configuration to update the app # https://docs.docker.com/compose/file-watch/#compose-watch-versus-bind-mounts diff --git a/multistage.Dockerfile b/multistage.Dockerfile index 54bc52b..bf57403 100644 --- a/multistage.Dockerfile +++ b/multistage.Dockerfile @@ -5,6 +5,9 @@ FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy +# Omit development dependencies +ENV UV_NO_DEV=1 + # Disable Python downloads, because we want to use the system interpreter # across both images. If using a managed Python version, it needs to be # copied from the build image into the final image; see `standalone.Dockerfile` @@ -15,10 +18,10 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --locked --no-install-project --no-dev + uv sync --locked --no-install-project COPY . /app RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --locked --no-dev + uv sync --locked # Then, use a final image without uv diff --git a/standalone.Dockerfile b/standalone.Dockerfile index ae09f61..ac51c21 100644 --- a/standalone.Dockerfile +++ b/standalone.Dockerfile @@ -4,6 +4,9 @@ FROM ghcr.io/astral-sh/uv:bookworm-slim AS builder ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy +# Omit development dependencies +ENV UV_NO_DEV=1 + # Configure the Python directory so it is consistent ENV UV_PYTHON_INSTALL_DIR=/python @@ -17,10 +20,10 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --locked --no-install-project --no-dev + uv sync --locked --no-install-project COPY . /app RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --locked --no-dev + uv sync --locked # Then, use a final image without uv FROM debian:bookworm-slim