feat: adds Containerfile with frontend serving
Some checks failed
ci / ruff (push) Successful in 4s
ci / ty (push) Failing after 4s
ci / tests (push) Failing after 8s

This commit is contained in:
Iain Learmonth 2026-06-22 14:24:34 +01:00
parent c28b4dc37b
commit 9e1d6026b5
5 changed files with 56 additions and 7 deletions

View file

@ -1 +1 @@
3.14
3.12

42
Containerfile Normal file
View file

@ -0,0 +1,42 @@
FROM node:22-slim AS react-builder
WORKDIR /app
COPY frontend/ /app/
RUN --mount=type=cache,target=/root/.npm npm ci
RUN npm run build # Outputs to /app/dist
FROM ghcr.io/astral-sh/uv:python3.12-trixie-slim AS python-builder
ENV UV_PYTHON_DOWNLOADS=0
WORKDIR /app
# Install dependencies first (layer caching)
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-editable
# Copy project source and install the project itself
COPY ./ /app/
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked --no-editable
FROM python:3.12-slim-trixie
WORKDIR /app
COPY alembic /app/alembic
COPY alembic.ini /app
COPY src /app/src
COPY --from=python-builder /app/.venv /app/.venv
COPY --from=react-builder /app/dist /app/static
# Ensure venv is on PATH
ENV PATH="/app/.venv/bin:$PATH" \
UV_PYTHON_DOWNLOADS=0
EXPOSE 8000
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]

View file

@ -8,7 +8,7 @@ requires-python = ">=3.12"
dependencies = [
"alembic>=1.18.4",
"email-validator>=2.3.0",
"fastapi>=0.136.3",
"fastapi>=0.138.0",
"httptools>=0.7.1",
"httpx>=0.28.1",
"itsdangerous>=2.2.0",
@ -34,11 +34,13 @@ line-length = 92
[tool.ruff.format]
quote-style = "double"
indent-style = "tab"
[tool.uv]
add-bounds = "major"
exclude-newer = "P2W"
exclude-newer-package = {
"fastapi" = "2026-06-22T00:00:00Z"
}
[dependency-groups]
dev = [

View file

@ -77,3 +77,5 @@ if settings.DISABLE_AUTH and (settings.ENVIRONMENT == Environment.LOCAL):
app.include_router(api_router)
app.frontend("/ui", directory="/app/static", fallback="index.html")

11
uv.lock generated
View file

@ -6,6 +6,9 @@ requires-python = ">=3.12"
exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values.
exclude-newer-span = "P2W"
[options.exclude-newer-package]
fastapi = "2026-06-22T00:00:00Z"
[[package]]
name = "alembic"
version = "1.18.4"
@ -238,7 +241,7 @@ dev = [
requires-dist = [
{ name = "alembic", specifier = ">=1.18.4" },
{ name = "email-validator", specifier = ">=2.3.0" },
{ name = "fastapi", specifier = ">=0.136.3" },
{ name = "fastapi", specifier = ">=0.138.0" },
{ name = "httptools", specifier = ">=0.7.1" },
{ name = "httpx", specifier = ">=0.28.1" },
{ name = "itsdangerous", specifier = ">=2.2.0" },
@ -349,7 +352,7 @@ wheels = [
[[package]]
name = "fastapi"
version = "0.136.3"
version = "0.138.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-doc" },
@ -358,9 +361,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/81/2d/ff8d91d7b564d464629a0fd50a4489c97fcb836ac230bf3a7269232a9b1f/fastapi-0.136.3.tar.gz", hash = "sha256:e487fae93ad408e6f47641ee4dfe389864fd7bec92e547ea8498fc13f43e83ab", size = 396410, upload-time = "2026-05-23T18:53:15.192Z" }
sdist = { url = "https://files.pythonhosted.org/packages/5b/58/ff455d9fe47c60abadb34b9e05a304b1f05f5ab8000ac01565156b6f5e43/fastapi-0.138.0.tar.gz", hash = "sha256:d445a4877636ad191e7053e08c9bf98cb921a6756776848400bb773d1740c061", size = 419240, upload-time = "2026-06-20T01:18:05.259Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/82/45359b62a067409bd929ae8a56b8ed13e5a8c8a61194b3c236920999ab83/fastapi-0.136.3-py3-none-any.whl", hash = "sha256:3d2a69bdf04b7e9f3afa292c3bc7a98816bbfafa10bc9b45f3f3700d2f761620", size = 117481, upload-time = "2026-05-23T18:53:16.924Z" },
{ url = "https://files.pythonhosted.org/packages/6c/ff/8496d9847a5fedae775eb49460722d3efaa80487854273e9647ae876218c/fastapi-0.138.0-py3-none-any.whl", hash = "sha256:b6f54fd1bd72c80b0f899f172c61a600f6f7af9b43d4d772a018f35624048cb0", size = 126779, upload-time = "2026-06-20T01:18:03.483Z" },
]
[[package]]