diff --git a/.dockerignore b/.dockerignore index 396f0da3e5..85ea8d5e59 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,6 +5,10 @@ **/.DS_Store **/.vscode **/node_modules +**/.turbo +**/coverage +**/dist +**/build # Specific patterns to ignore data-node @@ -12,6 +16,33 @@ meili_data* librechat* Dockerfile* docs +logs +uploads +images +api/data +archive +release +test-image* +dump.rdb +*.log +*.db +*.db-* +*.sqlite +*.sqlite-* +*.code-workspace +*.local.md +auth.json +cache.json +codedb.snapshot +junit.xml +monospace.json +owner.yml +vite-output.log +playwright-report +test-results +e2e/playwright-report +e2e/specs/.test-results +playwright/.cache # Ignore all hidden files .* diff --git a/Dockerfile b/Dockerfile index 8fd104b5a5..eecf185e32 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,60 +1,94 @@ # v0.8.5 -# Base node image -FROM node:20-alpine AS node - -RUN apk upgrade --no-cache -RUN apk add --no-cache jemalloc -RUN apk add --no-cache python3 py3-pip uv - -# Set environment variable to use jemalloc -ENV LD_PRELOAD=/usr/lib/libjemalloc.so.2 - -# Add `uv` for extended MCP support -COPY --from=ghcr.io/astral-sh/uv:0.9.5-python3.12-alpine /usr/local/bin/uv /usr/local/bin/uvx /bin/ -RUN uv --version - # Set configurable max-old-space-size with default ARG NODE_MAX_OLD_SPACE_SIZE=6144 -RUN mkdir -p /app && chown node:node /app +# Base for all builds +FROM node:20-alpine AS base-min +RUN apk upgrade --no-cache +RUN apk add --no-cache jemalloc +# Set environment variable to use jemalloc +ENV LD_PRELOAD=/usr/lib/libjemalloc.so.2 + WORKDIR /app +RUN apk --no-cache add curl +RUN npm config set fetch-retry-maxtimeout 600000 && \ + npm config set fetch-retries 5 && \ + npm config set fetch-retry-mintimeout 15000 +RUN chown node:node /app +COPY --chown=node:node package*.json ./ +COPY --chown=node:node packages/data-provider/package*.json ./packages/data-provider/ +COPY --chown=node:node packages/api/package*.json ./packages/api/ +COPY --chown=node:node packages/data-schemas/package*.json ./packages/data-schemas/ +COPY --chown=node:node packages/client/package*.json ./packages/client/ +COPY --chown=node:node client/package*.json ./client/ +COPY --chown=node:node api/package*.json ./api/ +# Install all dependencies for every build +FROM base-min AS base +WORKDIR /app +RUN npm ci + +# Build `data-provider` package +FROM base AS data-provider-build +WORKDIR /app/packages/data-provider +COPY packages/data-provider ./ +RUN npm run build + +# Build `data-schemas` package +FROM base AS data-schemas-build +WORKDIR /app/packages/data-schemas +COPY packages/data-schemas ./ +COPY --from=data-provider-build /app/packages/data-provider/dist /app/packages/data-provider/dist +RUN npm run build + +# Build `api` package +FROM base AS api-package-build +WORKDIR /app/packages/api +COPY packages/api ./ +COPY --from=data-provider-build /app/packages/data-provider/dist /app/packages/data-provider/dist +COPY --from=data-schemas-build /app/packages/data-schemas/dist /app/packages/data-schemas/dist +RUN npm run build + +# Build `client` package +FROM base AS client-package-build +WORKDIR /app/packages/client +COPY packages/client ./ +RUN npm run build + +# Client build +FROM base AS client-build +WORKDIR /app/client +COPY client ./ +COPY --from=data-provider-build /app/packages/data-provider/dist /app/packages/data-provider/dist +COPY --from=client-package-build /app/packages/client/dist /app/packages/client/dist +COPY --from=client-package-build /app/packages/client/src /app/packages/client/src +ARG NODE_MAX_OLD_SPACE_SIZE +ENV NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}" +RUN npm run build + +# Node API setup (including client dist) +FROM base-min AS node +# Add `uv` for extended MCP support +COPY --from=ghcr.io/astral-sh/uv:0.6.13 /uv /uvx /bin/ +RUN uv --version +WORKDIR /app USER node - -COPY --chown=node:node package.json package-lock.json ./ -COPY --chown=node:node api/package.json ./api/package.json -COPY --chown=node:node client/package.json ./client/package.json -COPY --chown=node:node packages/data-provider/package.json ./packages/data-provider/package.json -COPY --chown=node:node packages/data-schemas/package.json ./packages/data-schemas/package.json -COPY --chown=node:node packages/api/package.json ./packages/api/package.json - -RUN \ - # Allow mounting of these files, which have no default - touch .env ; \ - # Create directories for the volumes to inherit the correct permissions - mkdir -p /app/client/public/images /app/logs /app/uploads ; \ - npm config set fetch-retry-maxtimeout 600000 ; \ - npm config set fetch-retries 5 ; \ - npm config set fetch-retry-mintimeout 15000 ; \ - npm ci --no-audit - -COPY --chown=node:node . . - -RUN \ - # React client build with configurable memory - NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}" npm run frontend; \ - npm prune --production; \ +# Install only runtime workspaces so frontend-only packages stay out of the API image. +RUN npm ci --omit=dev --include-workspace-root=false \ + --workspace api \ + --workspace packages/api \ + --workspace packages/data-provider \ + --workspace packages/data-schemas && \ npm cache clean --force - -# Node API setup +COPY --chown=node:node api ./api +COPY --chown=node:node config ./config +COPY --chown=node:node --from=data-provider-build /app/packages/data-provider/dist ./packages/data-provider/dist +COPY --chown=node:node --from=data-schemas-build /app/packages/data-schemas/dist ./packages/data-schemas/dist +COPY --chown=node:node --from=api-package-build /app/packages/api/dist ./packages/api/dist +COPY --chown=node:node --from=client-build /app/client/dist ./client/dist +RUN mkdir -p /app/client/public/images /app/api/logs /app/uploads +WORKDIR /app/api EXPOSE 3080 ENV HOST=0.0.0.0 -CMD ["npm", "run", "backend"] - -# Optional: for client with nginx routing -# FROM nginx:stable-alpine AS nginx-client -# WORKDIR /usr/share/nginx/html -# COPY --from=node /app/client/dist /usr/share/nginx/html -# COPY client/nginx.conf /etc/nginx/conf.d/default.conf -# ENTRYPOINT ["nginx", "-g", "daemon off;"] +CMD ["node", "server/index.js"] diff --git a/Dockerfile.multi b/Dockerfile.multi index 778a9dba9f..791ecf25b7 100644 --- a/Dockerfile.multi +++ b/Dockerfile.multi @@ -16,13 +16,14 @@ RUN apk --no-cache add curl RUN npm config set fetch-retry-maxtimeout 600000 && \ npm config set fetch-retries 5 && \ npm config set fetch-retry-mintimeout 15000 -COPY package*.json ./ -COPY packages/data-provider/package*.json ./packages/data-provider/ -COPY packages/api/package*.json ./packages/api/ -COPY packages/data-schemas/package*.json ./packages/data-schemas/ -COPY packages/client/package*.json ./packages/client/ -COPY client/package*.json ./client/ -COPY api/package*.json ./api/ +RUN chown node:node /app +COPY --chown=node:node package*.json ./ +COPY --chown=node:node packages/data-provider/package*.json ./packages/data-provider/ +COPY --chown=node:node packages/api/package*.json ./packages/api/ +COPY --chown=node:node packages/data-schemas/package*.json ./packages/data-schemas/ +COPY --chown=node:node packages/client/package*.json ./packages/client/ +COPY --chown=node:node client/package*.json ./client/ +COPY --chown=node:node api/package*.json ./api/ # Install all dependencies for every build FROM base-min AS base @@ -73,14 +74,21 @@ FROM base-min AS api-build COPY --from=ghcr.io/astral-sh/uv:0.6.13 /uv /uvx /bin/ RUN uv --version WORKDIR /app -# Install only production deps -RUN npm ci --omit=dev -COPY api ./api -COPY config ./config -COPY --from=data-provider-build /app/packages/data-provider/dist ./packages/data-provider/dist -COPY --from=data-schemas-build /app/packages/data-schemas/dist ./packages/data-schemas/dist -COPY --from=api-package-build /app/packages/api/dist ./packages/api/dist -COPY --from=client-build /app/client/dist ./client/dist +USER node +# Install only runtime workspaces so frontend-only packages stay out of the API image. +RUN npm ci --omit=dev --include-workspace-root=false \ + --workspace api \ + --workspace packages/api \ + --workspace packages/data-provider \ + --workspace packages/data-schemas && \ + npm cache clean --force +COPY --chown=node:node api ./api +COPY --chown=node:node config ./config +COPY --chown=node:node --from=data-provider-build /app/packages/data-provider/dist ./packages/data-provider/dist +COPY --chown=node:node --from=data-schemas-build /app/packages/data-schemas/dist ./packages/data-schemas/dist +COPY --chown=node:node --from=api-package-build /app/packages/api/dist ./packages/api/dist +COPY --chown=node:node --from=client-build /app/client/dist ./client/dist +RUN mkdir -p /app/client/public/images /app/api/logs /app/uploads WORKDIR /app/api EXPOSE 3080 ENV HOST=0.0.0.0