/ Dockerfile
Dockerfile
1 FROM node:lts AS frontend-builder 2 3 WORKDIR /frontend 4 COPY frontend/package*.json ./ 5 RUN npm install 6 COPY frontend/ ./ 7 RUN npm run build 8 9 10 FROM python:3.12 AS backend-builder 11 12 RUN apt-get update && apt-get install --no-install-recommends -y postgresql-client python3-dev ffmpeg \ 13 && apt-get clean -y && rm -rf /var/lib/apt/lists/* 14 15 COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv 16 17 WORKDIR /app 18 19 COPY pyproject.toml uv.lock ./ 20 # `--no-install-project` skips building the local workspace package 21 # (restai-core). Without it uv would try to build a wheel here and 22 # hatchling would need README.md + the package source — but we only 23 # copied pyproject.toml + uv.lock at this point on purpose, so we keep 24 # the dependency-install layer cacheable across source changes. The 25 # runtime runs `python main.py` directly from /app, so the package 26 # never needs to be importable as an installed dist anyway. 27 RUN uv sync --frozen --no-group gpu --no-group dev --no-install-project 28 29 COPY . /app 30 31 32 FROM python:3.12-slim AS runtime 33 34 RUN apt-get update && apt-get install --no-install-recommends -y postgresql-client ffmpeg \ 35 && apt-get clean -y && rm -rf /var/lib/apt/lists/* 36 37 RUN useradd --user-group --system --create-home --no-log-init user \ 38 && mkdir -p /home/user/.cache /home/user/.local/share \ 39 && chown -R user:user /home/user 40 41 USER user 42 WORKDIR /app 43 44 COPY --from=frontend-builder /frontend/build /app/frontend/build 45 COPY --from=backend-builder --chown=user:user /app/.venv /app/.venv 46 COPY --chown=user:user . /app 47 48 EXPOSE 9000 49 50 HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \ 51 CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:9000/health/live')" || exit 1 52 53 CMD ["sh", "-c", ".venv/bin/python database.py && .venv/bin/python main.py"]