50 lines
1.3 KiB
Docker
50 lines
1.3 KiB
Docker
# ── Stage 1: Build the SvelteKit UI ──────────────────────────────────────────
|
|
FROM node:22-alpine AS ui-builder
|
|
WORKDIR /app
|
|
|
|
COPY ui/package*.json ./ui/
|
|
RUN cd ui && npm ci --legacy-peer-deps
|
|
|
|
# UI source + shared server types (needed for $types alias)
|
|
COPY ui/ ./ui/
|
|
COPY server/ ./server/
|
|
|
|
WORKDIR /app/ui
|
|
ENV NODE_ENV=production
|
|
RUN npm run build
|
|
|
|
# ── Stage 2: Runtime (API + compiled UI) ─────────────────────────────────────
|
|
FROM node:22-alpine
|
|
WORKDIR /app
|
|
|
|
# API dependencies (tsx needed at runtime for ESM TypeScript)
|
|
COPY package*.json ./
|
|
RUN npm ci
|
|
|
|
# API source
|
|
COPY bin/ ./bin/
|
|
COPY server/ ./server/
|
|
COPY tsconfig*.json ./
|
|
|
|
# Pre-built UI from stage 1
|
|
COPY --from=ui-builder /app/ui/build ./ui/build
|
|
COPY --from=ui-builder /app/ui/package*.json ./ui/
|
|
RUN cd ui && npm ci --omit=dev --legacy-peer-deps
|
|
|
|
# SQLite volume mount point
|
|
RUN mkdir -p /app/data
|
|
|
|
ENV NODE_ENV=production
|
|
ENV DB_PATH=/app/data/market-screener.db
|
|
ENV PORT=3000
|
|
ENV UI_PORT=3001
|
|
|
|
EXPOSE 3000 3001
|
|
|
|
# Run both processes; if either dies the container exits
|
|
CMD ["npx", "concurrently", \
|
|
"--kill-others", \
|
|
"--names", "api,ui", \
|
|
"tsx bin/server.ts", \
|
|
"node ui/build/index.js"]
|