diff --git a/.dockerignore b/.dockerignore index e825df4..c77e9bc 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,6 +5,7 @@ node_modules data/*.db data/*.db-shm data/*.db-wal +backend/data .env* npm-debug.log* .DS_Store diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 669a1e3..15f3e12 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -27,10 +27,10 @@ jobs: push: true tags: ${{ vars.REGISTRY }}/${{ gitea.repository_owner }}/sixflagssupercalendar:web - - name: Build and push scraper image + - name: Build and push backend image uses: docker/build-push-action@v6 with: context: . - target: scraper + target: backend push: true - tags: ${{ vars.REGISTRY }}/${{ gitea.repository_owner }}/sixflagssupercalendar:scraper + tags: ${{ vars.REGISTRY }}/${{ gitea.repository_owner }}/sixflagssupercalendar:backend diff --git a/.gitignore b/.gitignore index 070419f..d772b82 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ yarn-error.log* /data/*.db /data/*.db-shm /data/*.db-wal +/backend/data/ parks.db # env files diff --git a/Dockerfile b/Dockerfile index 8c141af..92f9195 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,21 @@ -# Stage 1: Install all dependencies (dev included — scraper needs tsx + playwright) -FROM node:22-bookworm-slim AS deps -RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ && \ - rm -rf /var/lib/apt/lists/* +# ── builder: Next.js production build ──────────────────────────────────────── +FROM node:22-bookworm-slim AS builder WORKDIR /app COPY package.json package-lock.json* ./ RUN npm ci - -# Stage 2: Build the Next.js app -FROM deps AS builder COPY . . RUN npm run build +# ── backend-deps: backend node_modules (better-sqlite3 needs build tools) ──── +FROM node:22-bookworm-slim AS backend-deps +RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ && \ + rm -rf /var/lib/apt/lists/* +WORKDIR /app +COPY backend/package.json backend/package-lock.json* ./ +RUN npm ci + # ── web ────────────────────────────────────────────────────────────────────── -# Minimal Next.js runner. No playwright, no tsx, no scripts. -# next build --output standalone bundles its own node_modules (incl. better-sqlite3). +# Minimal Next.js standalone runner. No database, no native modules. FROM node:22-bookworm-slim AS web WORKDIR /app @@ -27,44 +29,34 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder --chown=nextjs:nodejs /app/public ./public -RUN mkdir -p /app/data && chown nextjs:nodejs /app/data -VOLUME ["/app/data"] - USER nextjs EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0" CMD ["node", "server.js"] -# ── scraper ─────────────────────────────────────────────────────────────────── -# Scraper-only image. No Next.js output. Runs on a nightly schedule via -# scripts/scrape-schedule.sh. Staleness windows are configurable via env vars: -# PARK_HOURS_STALENESS_HOURS (default: 72) -# COASTER_STALENESS_HOURS (default: 720 = 30 days) -FROM node:22-bookworm-slim AS scraper +# ── backend ────────────────────────────────────────────────────────────────── +# Hono API server + node-cron scheduler. Owns the SQLite database exclusively. +FROM node:22-bookworm-slim AS backend WORKDIR /app ENV NODE_ENV=production -ENV PLAYWRIGHT_BROWSERS_PATH=/app/.playwright RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 nextjs -COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts -COPY --from=builder --chown=nextjs:nodejs /app/lib ./lib -COPY --from=builder --chown=nextjs:nodejs /app/tests ./tests -COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json -COPY --from=builder --chown=nextjs:nodejs /app/tsconfig.json ./tsconfig.json - -# Full node_modules — includes tsx, playwright, better-sqlite3, all devDeps -COPY --from=deps --chown=nextjs:nodejs /app/node_modules ./node_modules - -# Install Playwright Chromium + system libraries (runs as root, then fixes ownership) -RUN npx playwright install --with-deps chromium && \ - chown -R nextjs:nodejs /app/.playwright +COPY --from=backend-deps --chown=nextjs:nodejs /app/node_modules ./backend/node_modules +COPY --chown=nextjs:nodejs backend/src ./backend/src +COPY --chown=nextjs:nodejs backend/package.json ./backend/package.json +COPY --chown=nextjs:nodejs backend/tsconfig.json ./backend/tsconfig.json +COPY --chown=nextjs:nodejs lib ./lib RUN mkdir -p /app/data && chown nextjs:nodejs /app/data VOLUME ["/app/data"] USER nextjs -CMD ["sh", "/app/scripts/scrape-schedule.sh"] +EXPOSE 3001 +ENV PORT=3001 + +WORKDIR /app/backend +CMD ["npx", "tsx", "src/index.ts"] diff --git a/docker-compose.yml b/docker-compose.yml index 5703ed0..88e0065 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,21 +3,21 @@ services: image: gitea.thewrightserver.net/josh/sixflagssupercalendar:web ports: - "3000:3000" - volumes: - - park_data:/app/data environment: - NODE_ENV=production + - BACKEND_URL=http://backend:3001 restart: unless-stopped - scraper: - image: gitea.thewrightserver.net/josh/sixflagssupercalendar:scraper + backend: + image: gitea.thewrightserver.net/josh/sixflagssupercalendar:backend + ports: + - "3001:3001" volumes: - park_data:/app/data environment: - NODE_ENV=production - TZ=America/New_York - PARK_HOURS_STALENESS_HOURS=72 - - COASTER_STALENESS_HOURS=720 restart: unless-stopped volumes: