File size: 5,471 Bytes
7a30d73
 
 
 
 
 
 
 
 
 
 
 
 
bea31a2
7a30d73
 
 
 
7a52698
7a30d73
26e2a42
 
 
 
f020a40
 
 
26e2a42
f020a40
 
 
26e2a42
 
f020a40
 
26e2a42
 
 
 
7a30d73
 
 
 
 
 
 
26e2a42
 
 
7a30d73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1f11d61
 
26e2a42
 
7a30d73
 
7c166e1
 
7a30d73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# ============================================================
# BankBot AI β€” Hugging Face Spaces Dockerfile
#
# Single-container deployment:
#   Port 7860 (HF requirement) β†’ Nginx
#   Nginx β†’ Next.js (port 3000) for frontend
#   Nginx β†’ FastAPI (port 8000) for /api/* and /ws
#
# Build args:
#   NEXT_PUBLIC_API_URL  (default: relative /api proxy)
# ============================================================

# ─── Stage 1: Build Next.js frontend ─────────────────────────────────────────
FROM node:20-slim AS frontend-builder

WORKDIR /frontend

COPY frontend/package.json frontend/package-lock.json* ./
RUN npm install --legacy-peer-deps --quiet

# Copy only the necessary frontend files (deterministic for HF build context)
COPY frontend/package.json frontend/package-lock.json* ./
COPY frontend/next.config.mjs ./
COPY frontend/tsconfig.json ./
COPY frontend/postcss.config.mjs ./
COPY frontend/tailwind.config.ts ./
COPY frontend/components.json ./
COPY frontend/src ./src

# Create public dir if it doesn't exist (Next.js requires it for standalone output)
RUN mkdir -p public

# Verify app layout exists (better failure message in CI/HF logs)
RUN if [ ! -d "src/app" ]; then \
            echo "ERROR: no 'src/app' directory found in frontend - Next.js requires an app directory"; \
            ls -la /frontend || true; \
            ls -la /frontend/src || true; \
            exit 1; \
        fi

# In HF, frontend calls go through the same origin via Nginx proxy
# So NEXT_PUBLIC_API_URL is empty β€” rewrites handle /api/* internally
ARG NEXT_PUBLIC_API_URL=""
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
ENV NEXT_TELEMETRY_DISABLED=1

# Increase Node heap for Next.js builds to avoid OOM in constrained builders
ENV NODE_OPTIONS="--max-old-space-size=4096"

RUN npm run build

# ─── Stage 2: Python dependencies ────────────────────────────────────────────
FROM python:3.11-slim AS python-builder

WORKDIR /build

RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    libpq-dev \
    && rm -rf /var/lib/apt/lists/*

COPY backend/requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

# ─── Stage 3: Final runtime image ────────────────────────────────────────────
FROM python:3.11-slim AS runtime

# Install Node.js, Nginx, supervisord, curl
RUN apt-get update && apt-get install -y --no-install-recommends \
    nginx \
    supervisor \
    curl \
    libpq5 \
    ca-certificates \
    tesseract-ocr \
    tesseract-ocr-eng \
    xz-utils \
    && curl -fsSL https://nodejs.org/dist/v20.11.0/node-v20.11.0-linux-x64.tar.xz | tar -xJ --strip-components=1 -C /usr/local \
    && rm -rf /var/lib/apt/lists/*

ENV TESSDATA_PREFIX=/usr/share/tesseract-ocr/5/tessdata

# ── Python packages ───────────────────────────────────────────────────────────
COPY --from=python-builder /install /usr/local

# ── Backend ───────────────────────────────────────────────────────────────────
WORKDIR /app/backend
COPY backend/app/ ./app/
COPY backend/requirements.txt .

# ── Frontend (standalone build) ───────────────────────────────────────────────
WORKDIR /app/frontend
COPY --from=frontend-builder /frontend/.next/standalone ./
COPY --from=frontend-builder /frontend/.next/static ./.next/static
COPY --from=frontend-builder /frontend/public ./public

# ── Nginx config ──────────────────────────────────────────────────────────────
COPY hf/nginx.conf /etc/nginx/nginx.conf

# ── Supervisord config ────────────────────────────────────────────────────────
COPY hf/supervisord.conf /etc/supervisor/conf.d/bankbot.conf

# ── Startup script ────────────────────────────────────────────────────────────
COPY hf/start.sh /app/start.sh
RUN chmod +x /app/start.sh

# ── Writable dirs for non-root (HF runs as user 1000) ────────────────────────
RUN mkdir -p /app/data /var/log/supervisor /var/log/nginx /var/lib/nginx/body \
    && chmod -R 777 /app/data /var/log/supervisor /var/log/nginx \
    && chmod -R 777 /var/lib/nginx \
    && touch /run/nginx.pid && chmod 777 /run/nginx.pid \
    && chown -R 1000:1000 /app /var/log/supervisor /var/log/nginx /var/lib/nginx

# HF Spaces requires port 7860
EXPOSE 7860

# Health check
HEALTHCHECK --interval=30s --timeout=15s --start-period=60s --retries=5 \
    CMD curl -f http://localhost:7860/health || exit 1

# Run as user 1000 (HF default)
USER 1000

WORKDIR /app

CMD ["/app/start.sh"]