78 lines
3.6 KiB
Docker
78 lines
3.6 KiB
Docker
# syntax=docker/dockerfile:1
|
|
#
|
|
# Dungeons & Ground — production image.
|
|
#
|
|
# Build: docker build -t dungeons-ground .
|
|
# Run: docker run --env-file .env -p 3000:3000 dungeons-ground
|
|
#
|
|
# Required env vars at runtime (see .env.example):
|
|
# NUXT_PUBLIC_SUPABASE_URL, SUPABASE_URL, NUXT_PUBLIC_SUPABASE_ANON_KEY,
|
|
# SUPABASE_SERVICE_ROLE_KEY, plus the AI provider key (OPENROUTER_API_KEY
|
|
# or DEEPSEEK_API_KEY). REDIS_URL is optional.
|
|
# The Supabase schema is NOT created by the container; install
|
|
# supabase/bootstrap.sql (or run `pnpm db:ensure` with SUPABASE_DB_URL set)
|
|
# in your Supabase project before starting.
|
|
|
|
FROM node:18.20.8-slim AS base
|
|
|
|
ENV PNPM_HOME=/pnpm
|
|
ENV PATH=$PNPM_HOME:$PATH
|
|
RUN corepack enable && corepack prepare pnpm@10.15.0 --activate
|
|
|
|
WORKDIR /app
|
|
|
|
# ---------- Dependencies ----------
|
|
FROM base AS deps
|
|
|
|
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
|
COPY apps/web/package.json apps/web/package.json
|
|
COPY apps/worker/package.json apps/worker/package.json
|
|
COPY packages/shared/package.json packages/shared/package.json
|
|
COPY packages/game-engine/package.json packages/game-engine/package.json
|
|
|
|
RUN pnpm install --frozen-lockfile
|
|
|
|
# ---------- Build ----------
|
|
FROM deps AS build
|
|
|
|
COPY . .
|
|
# The web build explicitly loads ../../.env (--dotenv); an empty file keeps
|
|
# the build hermetic — all real values come from container env at runtime.
|
|
RUN touch .env && pnpm --filter @dng/web build
|
|
|
|
# ---------- Runtime ----------
|
|
FROM base AS runtime
|
|
|
|
ENV NODE_ENV=production
|
|
ENV HOST=0.0.0.0
|
|
ENV PORT=3000
|
|
|
|
WORKDIR /app
|
|
|
|
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
|
COPY apps/web/package.json apps/web/package.json
|
|
COPY apps/worker/package.json apps/worker/package.json
|
|
COPY packages/shared/package.json packages/shared/package.json
|
|
COPY packages/game-engine/package.json packages/game-engine/package.json
|
|
|
|
COPY --from=deps /app/node_modules node_modules
|
|
COPY --from=build /app/apps/web/.output apps/web/.output
|
|
COPY --from=build /app/apps/worker apps/worker
|
|
COPY --from=build /app/packages/shared packages/shared
|
|
COPY --from=build /app/packages/game-engine packages/game-engine
|
|
|
|
EXPOSE 3000
|
|
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
|
CMD node -e "fetch('http://127.0.0.1:3000/').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
|
|
|
# The Nuxt web server reads its config through Nuxt runtimeConfig, which is
|
|
# baked at build time and overridden at runtime only by NUXT_-prefixed env
|
|
# vars; the worker reads plain names (SUPABASE_URL, OPENROUTER_API_KEY, ...)
|
|
# directly. The entrypoint maps the plain .env.example names onto the NUXT_
|
|
# runtime overrides so `docker run --env-file .env` works for both processes.
|
|
# The web server runs in the foreground (PID 1); the AI worker runs alongside
|
|
# it in the background. Stop the container with `docker stop` — both die with
|
|
# it.
|
|
CMD ["sh", "-c", "export NUXT_SUPABASE_URL=\"${NUXT_SUPABASE_URL:-${SUPABASE_URL:-}}\" NUXT_SUPABASE_SERVICE_ROLE_KEY=\"${NUXT_SUPABASE_SERVICE_ROLE_KEY:-${SUPABASE_SERVICE_ROLE_KEY:-}}\" NUXT_AI_PROVIDER=\"${NUXT_AI_PROVIDER:-${AI_PROVIDER:-}}\" NUXT_OPENROUTER_API_KEY=\"${NUXT_OPENROUTER_API_KEY:-${OPENROUTER_API_KEY:-}}\" NUXT_OPENROUTER_MODEL=\"${NUXT_OPENROUTER_MODEL:-${OPENROUTER_MODEL:-}}\" NUXT_OPENROUTER_API_ENDPOINT=\"${NUXT_OPENROUTER_API_ENDPOINT:-${OPENROUTER_API_ENDPOINT:-}}\" NUXT_DEEPSEEK_API_KEY=\"${NUXT_DEEPSEEK_API_KEY:-${DEEPSEEK_API_KEY:-}}\" NUXT_DEEPSEEK_MODEL=\"${NUXT_DEEPSEEK_MODEL:-${DEEPSEEK_MODEL:-}}\" NUXT_DEEPSEEK_API_ENDPOINT=\"${NUXT_DEEPSEEK_API_ENDPOINT:-${DEEPSEEK_API_ENDPOINT:-}}\" NUXT_REDIS_URL=\"${NUXT_REDIS_URL:-${REDIS_URL:-}}\"; pnpm --filter @dng/worker start & exec node apps/web/.output/server/index.mjs"]
|