chore(deploy): production Dockerfiles for broker + web + env template
Some checks failed
CI / Tests / 🧪 Test (push) Has been cancelled
Some checks failed
CI / Tests / 🧪 Test (push) Has been cancelled
- apps/broker/Dockerfile: oven/bun 1.2-slim runtime, multi-stage, pnpm deps,
non-root bun user, GIT_SHA build-arg, /health-based HEALTHCHECK, port 7900
- apps/web/Dockerfile: Next.js 15 standalone, multi-stage, non-root nextjs
user, NEXT_PUBLIC_* baked as build args, port 3000
- .env.production.template: DATABASE_URL, BetterAuth, OAuth, broker caps;
no secrets
- Build context: repo root (pnpm workspace needs root pnpm-lock.yaml +
pnpm-workspace.yaml); build with -f apps/{broker,web}/Dockerfile .
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
47
apps/broker/Dockerfile
Normal file
47
apps/broker/Dockerfile
Normal file
@@ -0,0 +1,47 @@
|
||||
# claudemesh broker — production Dockerfile
|
||||
# Bun runtime (executes .ts directly, no build step required).
|
||||
# Build from repo root: docker build -f apps/broker/Dockerfile -t claudemesh-broker .
|
||||
|
||||
# Stage 1: resolve pnpm workspace + install deps (Bun base + standalone pnpm)
|
||||
FROM oven/bun:1.2 AS deps
|
||||
WORKDIR /app
|
||||
|
||||
# Install standalone pnpm binary (no Node needed — pnpm ships as a single ELF)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && \
|
||||
curl -fsSL "https://github.com/pnpm/pnpm/releases/download/v10.25.0/pnpm-linuxstatic-x64" -o /usr/local/bin/pnpm && \
|
||||
chmod +x /usr/local/bin/pnpm && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy full workspace (pnpm needs lockfile + all package.jsons to resolve workspace:* and catalog:)
|
||||
COPY . .
|
||||
|
||||
# Install all workspace deps (broker needs @turbostarter/db + @turbostarter/shared and their transitive deps)
|
||||
RUN pnpm install --frozen-lockfile --ignore-scripts
|
||||
|
||||
# Stage 2: minimal Bun runtime
|
||||
FROM oven/bun:1.2-slim AS runtime
|
||||
WORKDIR /app
|
||||
|
||||
# Git SHA baked in at build-time → surfaced on /health (spec: apps/broker/DEPLOY_SPEC.md)
|
||||
ARG GIT_SHA=unknown
|
||||
ENV GIT_SHA=$GIT_SHA
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV BROKER_PORT=7900
|
||||
|
||||
# Copy workspace root metadata + node_modules + only the packages the broker needs
|
||||
COPY --from=deps --chown=bun:bun /app/package.json /app/pnpm-workspace.yaml /app/pnpm-lock.yaml /app/.npmrc ./
|
||||
COPY --from=deps --chown=bun:bun /app/node_modules ./node_modules
|
||||
COPY --from=deps --chown=bun:bun /app/apps/broker ./apps/broker
|
||||
COPY --from=deps --chown=bun:bun /app/packages/db ./packages/db
|
||||
COPY --from=deps --chown=bun:bun /app/packages/shared ./packages/shared
|
||||
COPY --from=deps --chown=bun:bun /app/tooling/typescript ./tooling/typescript
|
||||
|
||||
EXPOSE 7900
|
||||
|
||||
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD bun -e "fetch('http://localhost:7900/health').then(r=>{process.exit(r.ok?0:1)}).catch(()=>process.exit(1))"
|
||||
|
||||
# Non-root user (oven/bun image ships with 'bun' uid 1000)
|
||||
USER bun
|
||||
CMD ["bun", "apps/broker/src/index.ts"]
|
||||
52
apps/web/Dockerfile
Normal file
52
apps/web/Dockerfile
Normal file
@@ -0,0 +1,52 @@
|
||||
# claudemesh web (Next.js) — production Dockerfile
|
||||
# Build from repo root: docker build -f apps/web/Dockerfile -t claudemesh-web .
|
||||
|
||||
# Stage 1: builder — install + turbo build (Next.js standalone output)
|
||||
FROM node:22-slim AS builder
|
||||
WORKDIR /app
|
||||
|
||||
RUN corepack enable && corepack prepare pnpm@10.25.0 --activate
|
||||
|
||||
# pnpm workspace needs full context to resolve workspace:* + catalog:
|
||||
COPY . .
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Build — SKIP_ENV_VALIDATION lets missing runtime vars pass (validated at startup instead)
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV SKIP_ENV_VALIDATION=1
|
||||
|
||||
# NEXT_PUBLIC_* vars are BAKED at build time in Next standalone — must be passed as build args
|
||||
ARG NEXT_PUBLIC_URL=https://claudemesh.com
|
||||
ARG NEXT_PUBLIC_PRODUCT_NAME=claudemesh
|
||||
ARG NEXT_PUBLIC_DEFAULT_LOCALE=en
|
||||
ENV NEXT_PUBLIC_URL=$NEXT_PUBLIC_URL
|
||||
ENV NEXT_PUBLIC_PRODUCT_NAME=$NEXT_PUBLIC_PRODUCT_NAME
|
||||
ENV NEXT_PUBLIC_DEFAULT_LOCALE=$NEXT_PUBLIC_DEFAULT_LOCALE
|
||||
|
||||
RUN npx turbo run build --filter=@claudemesh/web... --filter=web...
|
||||
|
||||
# Stage 2: runtime — standalone output only
|
||||
FROM node:22-slim AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV PORT=3000
|
||||
ENV HOSTNAME=0.0.0.0
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 nextjs
|
||||
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/web/.next/static
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public
|
||||
|
||||
USER nextjs
|
||||
EXPOSE 3000
|
||||
|
||||
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD node -e "fetch('http://localhost:3000').then(r=>{process.exit(r.ok?0:1)}).catch(()=>process.exit(1))"
|
||||
|
||||
CMD ["node", "apps/web/server.js"]
|
||||
Reference in New Issue
Block a user