Dockerfile
Rama main · réplica de lectura del repositorio original.
# syntax=docker/dockerfile:1
ARG NODE_VERSION=24.7.0
ARG PNPM_VERSION=10.34.5
ARG TURBO_VERSION=2.10.5
################################################################################
# Use node image for base image for all stages.
FROM node:${NODE_VERSION}-alpine AS base
ARG PNPM_VERSION
ARG TURBO_VERSION
# Set working directory for all build stages.
WORKDIR /usr/src/app
# Install the workspace package manager and task runner.
RUN --mount=type=cache,target=/root/.npm \
npm install -g pnpm@${PNPM_VERSION} turbo@${TURBO_VERSION} && \
pnpm --version && \
turbo --version
################################################################################
# Prune the workspace to the app and its dependencies. This runs on the native
# build platform so workspace graph preparation avoids QEMU emulation.
################################################################################
FROM --platform=$BUILDPLATFORM base AS prepare
COPY . .
RUN turbo prune @serial/app --docker
################################################################################
# Install the pruned workspace and build the application. This also runs on the
# native build platform because the output is platform-agnostic JavaScript.
################################################################################
FROM --platform=$BUILDPLATFORM base AS build-base
# Download all dependencies (including devDependencies) needed for building.
COPY --from=prepare /usr/src/app/out/json/ ./
COPY --from=prepare /usr/src/app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile
# Copy the pruned source after installing dependencies so source-only changes do
# not invalidate the dependency layer.
COPY --from=prepare /usr/src/app/out/full/ ./
ENV NODE_OPTIONS="--max-old-space-size=4096"
# Demo mode is an image-level capability because it includes a destructive
# scheduled task. Only the demo Compose file selects this build stage.
FROM build-base AS build-demo
RUN pnpm --filter @serial/app exec vite build --mode demo && \
cp apps/app/instrument.server.mjs apps/app/.output/server && \
pnpm --filter @serial/app run build:sw
# Run the standard build (without migrations - those run at container startup).
FROM build-base AS build
RUN pnpm --filter @serial/app run build:artifact
################################################################################
# Create a new stage to run the application with minimal runtime dependencies
# where the necessary files are copied from the build stage.
################################################################################
FROM base AS final-base
# Copy only the app's pruned workspace manifests and lockfile.
COPY --from=prepare /usr/src/app/out/json/ ./
COPY --from=prepare /usr/src/app/out/pnpm-lock.yaml ./pnpm-lock.yaml
# Install dependencies for the target platform.
# --ignore-scripts skips native compilation which is
# slow under QEMU and not needed at runtime.
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile --ignore-scripts
WORKDIR /usr/src/app/apps/app
# Copy migration files and source needed for running migrations
COPY --from=build-base /usr/src/app/apps/app/tsconfig.json ./tsconfig.json
COPY --from=build-base /usr/src/app/apps/app/src/server/db ./src/server/db
COPY --from=build-base /usr/src/app/apps/app/src/env.js ./src/env.js
COPY --from=build-base /usr/src/app/apps/app/src/lib/extension-auth.ts ./src/lib/extension-auth.ts
COPY --from=build-base /usr/src/app/apps/app/src/lib/content/descriptor.ts ./src/lib/content/descriptor.ts
COPY --from=build-base /usr/src/app/apps/app/src/lib/schemas/bulk.ts ./src/lib/schemas/bulk.ts
COPY --from=build-base /usr/src/app/apps/app/src/lib/views/contentFilter.ts ./src/lib/views/contentFilter.ts
COPY --from=build-base /usr/src/app/packages/extension-identity /usr/src/app/packages/extension-identity
# Catch missing transitive imports in the migration runtime before deployment.
RUN PUBLIC_BASE_URL=http://localhost \
BETTER_AUTH_SECRET=container-build-smoke-test \
KV_STORE=none \
NODE_ENV=production \
node --import=tsx -e "await import('./src/env.js'); await import('./src/server/db/schema.ts')"
# Expose the port that the application listens on.
EXPOSE 3000
# Run migrations then start the application.
CMD ["sh", "-c", "node --experimental-specifier-resolution=node --loader ts-node/esm src/server/db/migrate.js 2>/dev/null || node --import=tsx src/server/db/migrate.ts && node .output/server/index.mjs"]
FROM final-base AS final-demo
COPY --from=build-demo /usr/src/app/apps/app/.output ./.output
# Keep the standard image as the default Dockerfile target.
FROM final-base AS final
COPY --from=build /usr/src/app/apps/app/.output ./.output