build: optimize docker runtime image

This commit is contained in:
Marco Beretta 2026-05-08 13:17:41 +02:00
parent b1b9f74004
commit 9a3419e6c7
No known key found for this signature in database
GPG key ID: D918033D8E74CC11
3 changed files with 137 additions and 64 deletions

View file

@ -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
.*

View file

@ -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"]

View file

@ -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