# syntax=docker/dockerfile:1 # Stage 1: Install dependencies FROM oven/bun:1.3.14-alpine AS deps WORKDIR /app # Copy only package files to leverage Docker layer caching COPY package.json bun.lock ./ # The Docker layer already caches dependencies until package.json or bun.lock # changes. Avoid a persistent Bun cache mount here: stale package artifacts can # survive dependency upgrades and produce a node_modules tree that disagrees # with bun.lock. RUN bun install --frozen-lockfile # Stage 2: Build the application FROM deps AS builder ARG TARGETARCH ENV NEXT_TELEMETRY_DISABLED=1 COPY . . # Build Next.js RUN --mount=type=cache,target=/app/.next/cache \ bun run build # The standalone tracer includes both glibc and musl Sharp packages. Alpine only # needs musl, so prune the incompatible copy before it enters a runtime layer. RUN rm -rf \ ".next/standalone/node_modules/@img/sharp-linux-${TARGETARCH}" \ ".next/standalone/node_modules/@img/sharp-libvips-linux-${TARGETARCH}" # Stage 3: Production runner FROM oven/bun:1.3.14-alpine AS runner WORKDIR /app ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 ENV HOSTNAME=0.0.0.0 ENV PORT=3000 # Copy the standalone server and static assets without the full dependency tree COPY --from=builder /app/.next/standalone ./ COPY --from=builder /app/public ./public COPY --from=builder /app/.next/static ./.next/static EXPOSE 3000 CMD ["bun", "server.js"] # Stage 4: Scheduled video upload worker FROM deps AS video-upload-worker COPY . . CMD ["bun", "run", "worker/video-upload.ts"]