Repository navigation
Expand file tree
/
Copy pathDockerfile
More file actions
72 lines (59 loc) · 2.95 KB
/
Copy pathDockerfile
File metadata and controls
72 lines (59 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# ──────────────────────────────────────────────────────────────────
# OpenGTM — Production Dockerfile
# Multi-stage build: Frontend (Bun workspace) → Backend (Python 3.13)
# ──────────────────────────────────────────────────────────────────
# Stage 1: Build Frontend
# The repo is a Bun workspace with a single root bun.lock, so the install has
# to run from the root with every workspace manifest present for
# --frozen-lockfile to resolve. Only apps/web is built here.
FROM oven/bun:1 AS frontend-builder
WORKDIR /app
COPY package.json bun.lock ./
COPY apps/web/package.json ./apps/web/
COPY apps/web/vendor/ ./apps/web/vendor/
COPY apps/api/package.json ./apps/api/
COPY apps/docs/package.json ./apps/docs/
COPY packages/chrome-extension/package.json ./packages/chrome-extension/
COPY packages/n8n-nodes-yupcha/package.json ./packages/n8n-nodes-yupcha/
RUN bun install --frozen-lockfile --ignore-scripts
COPY apps/web/ ./apps/web/
RUN bun run --cwd apps/web build
# Stage 2: Backend + serve static
FROM python:3.13-slim
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc libpq-dev curl \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies
COPY apps/api/pyproject.toml apps/api/setup.py* apps/api/setup.cfg* ./apps/api/
COPY pyproject.toml* ./
RUN pip install --no-cache-dir -e ./apps/api 2>/dev/null || \
(cd apps/api && pip install --no-cache-dir -e .) 2>/dev/null || \
echo "No pyproject.toml install, will use requirements.txt"
# Fallback: requirements.txt
COPY apps/api/requirements.txt* ./apps/api/
RUN if [ -f apps/api/requirements.txt ]; then pip install --no-cache-dir -r apps/api/requirements.txt; fi
# Copy backend code
COPY apps/api/ ./apps/api/
# Alembic is the production schema authority. These live at the repository
# root, so copying apps/api alone produces an image that can create tables but
# cannot apply migrations or RLS policies.
COPY alembic.ini ./alembic.ini
COPY migrations/ ./migrations/
# Copy built frontend from Stage 1
COPY --from=frontend-builder /app/apps/web/dist ./apps/web/dist
# Set environment
ENV PYTHONPATH=/app
ENV ROOT_DIR=/app
# NOTE: Do NOT hardcode a SQLite DB_PATH here — it would shadow the documented
# Postgres default. The database is selected via DATABASE_URL (see
# docker-compose.yml / .env.example). Legacy code that still reads DB_PATH falls
# back to its own default for the sqlite meta files under /app/data.
# Create data directory
RUN mkdir -p /app/data
# Health check
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
EXPOSE 8000
CMD ["uvicorn", "apps.api.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]