danny-avila / LibreChat

Enhanced ChatGPT Clone: Features Anthropic, AWS, OpenAI, Assistants API, Azure, Groq, o1, GPT-4o, Mistral, OpenRouter, Vertex AI, Gemini, Artifacts, AI model switching, message search, langchain, DALL-E-3, ChatGPT Plugins, OpenAI Functions, Secure Multi-User System, Presets, completely open-source for self-hosting. Actively in public development.
https://librechat.ai/
MIT License
17.98k stars 3k forks source link

Enhancement: Improve Dockerfile for cached layer handling #2158

Open virtuman opened 6 months ago

virtuman commented 6 months ago

What features would you like to see added?

Docker takes too long, couple simple manipulations will drastically improve build times and utilize cached layers, to avoid entire image rebuild on each run. You can see screenshots below, to notice build time differences

More details

something like this would result in a quicker build, given that you use runner that has docker cache, or pull :latest and use as cache. And minimize number of RUN commands, so that it doesn't persist layer after each command

here're the differences:

all steps that i marked, will re-use cached layers, and only app build will re-run on every rebuild of the app

this way, image build will go to seconds, if you use runners that have perstitent docker or use --pull in docker build command, to re-use cached layers (that will add few extra seconds to pull last built image as cache from docker registry)

Below is a working version of Dockerfile that I use it myself

# Base node image
FROM node:18-alpine AS node

RUN apk add --no-cache g++ make py3-pip curl && \
        npm config set fetch-retry-maxtimeout 300000 && \
        npm install -g node-gyp npm

USER node

WORKDIR /app

# Copy package.json and package-lock.json (if available)
COPY --chown=node:node package.json package-lock.json* ./
COPY --chown=node:node config config/
COPY --chown=node:node api/package.json api/
COPY --chown=node:node client/package.json client/
COPY --chown=node:node packages/data-provider/package.json packages/data-provider/

# Install dependencies
RUN npm install --no-audit
# Allow mounting of these files, which have no default
# values.
RUN touch .env

# Copy the rest of the application code
COPY --chown=node:node . .

# React client build
ENV NODE_OPTIONS="--max-old-space-size=2048"
RUN npm run frontend

# Node API setup
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
# EXPOSE 80
# ENTRYPOINT ["nginx", "-g", "daemon off;"]

Which components are impacted by your request?

No response

Pictures

Initial Build - before caching or if package-json files not changed

Initial Build - before caching or if package-json files not changed

Consequent rebuild without code changes

Consequent rebuild without code changes

Code changed in client only

Code changed in client only

Code of Conduct

danny-avila commented 6 months ago

Feel free to submit a PR. I made some Dockerfile changes today, by the way, in case that affected your build time.

ochen1 commented 6 months ago

Just saw this, I think my PR #2275 aims to address this issue to some extent.

danny-avila commented 6 months ago

Just saw this, I think my PR #2275 aims to address this issue to some extent.

yes your PR addresses it for Dockerfile.multi but could use help to optimize the default Dockerfile