feat(docker): use multi-stage Docker builds for smaller images (#1614)

# Description

Currently, the production Docker images are very large, sitting at 4.17
GB for the frontend image, and 3.49 GB for backend images. This change
adds multi-stage builds, to optimize the image sizes, which results in
the following improvements:

- frontend image size: 4.17 GB -> 1.64 GB
- backend image size: 3.49 GB -> 1.71 GB

I hope this is appropriate as there is no open issue for this that I
know of.
I implemented this change and tested it locally, and would be glad to
discuss this and open an issue if necessary.

## Checklist before requesting a review

Please delete options that are not relevant.

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented hard-to-understand areas
- [x] New and existing unit tests pass locally with my changes

## Screenshots (if appropriate):
Image sizes before:
<img width="1416" alt="image"
src="https://github.com/StanGirard/quivr/assets/8296549/fcbb020f-8165-4549-ae30-823318691ec6">

Image sizes after:
<img width="1416" alt="image"
src="https://github.com/StanGirard/quivr/assets/8296549/d3f43c78-be26-4c38-9d23-9c1b0e9e37f2">
This commit is contained in:
Mohamed Messaad 2023-11-13 10:13:56 +01:00 committed by GitHub
parent db5a6e4b9b
commit 71d4a63a17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 18 deletions

View File

@ -1,10 +1,10 @@
# Using a slim version for a smaller base image # First stage: Build environment
FROM python:3.11-slim-bullseye FROM python:3.11-slim-bullseye as builder
ARG DEV_MODE ARG DEV_MODE
ENV DEV_MODE=$DEV_MODE ENV DEV_MODE=$DEV_MODE
# Install GEOS library, Rust, and other dependencies, then clean up # Install GEOS library, Rust, and other build-time dependencies
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
libgeos-dev \ libgeos-dev \
libcurl4-openssl-dev \ libcurl4-openssl-dev \
@ -20,19 +20,43 @@ RUN apt-get update && apt-get install -y \
# Add Rust binaries to the PATH # Add Rust binaries to the PATH
ENV PATH="/root/.cargo/bin:${PATH}" ENV PATH="/root/.cargo/bin:${PATH}"
# Create a virtual environment and activate it
RUN python -m venv /venv
ENV PATH="/venv/bin:$PATH"
WORKDIR /code WORKDIR /code
# Copy just the requirements first # Copy just the requirements first
COPY ./requirements.txt . COPY ./requirements.txt .
# Upgrade pip # Upgrade pip and install requirements
RUN pip install --upgrade pip RUN pip install --upgrade pip && \
pip install --no-cache-dir -r requirements.txt --timeout 200
# Increase timeout to wait for the new installation
RUN pip install --no-cache-dir -r requirements.txt --timeout 200
# Install development tools if in DEV_MODE
RUN if [ "$DEV_MODE" = "true" ]; then pip install --no-cache debugpy --timeout 200; fi RUN if [ "$DEV_MODE" = "true" ]; then pip install --no-cache debugpy --timeout 200; fi
FROM python:3.11-slim-bullseye as runtime
ARG DEV_MODE
ENV DEV_MODE=$DEV_MODE
# Create and activate the virtual environment
ENV PATH="/venv/bin:$PATH"
# Install runtime dependencies
RUN apt-get update && apt-get install -y \
pandoc \
binutils && \
rm -rf /var/lib/apt/lists/* && apt-get clean
WORKDIR /code
# Copy the virtual environment from the builder stage
COPY --from=builder /venv /venv
# Copy the rest of the application # Copy the rest of the application
COPY . . COPY . .

View File

@ -1,29 +1,47 @@
FROM node:18.13.0-alpine # First stage: Build environment
FROM node:18.13.0-alpine as builder
# Install Python and essential build tools # Install Python and essential build tools
RUN apk add --update --no-cache python3 make g++ && ln -sf python3 /usr/bin/python RUN apk add --update --no-cache python3 make g++ && ln -sf python3 /usr/bin/python
RUN python3 -m ensurepip RUN python3 -m ensurepip
RUN pip3 install --no-cache --upgrade pip setuptools RUN pip3 install --no-cache --upgrade pip setuptools
# Create the directory on the node image # Create a Python virtual environment
# where our Next.js app will live RUN python3 -m venv /venv
RUN mkdir -p /app ENV PATH="/venv/bin:$PATH"
# Set /app as the working directory # Create the directory where our app will live
RUN mkdir -p /app
WORKDIR /app WORKDIR /app
# Copy package.json and yarn.lock # Copy package.json and yarn.lock to the working directory
# to the /app working directory
COPY package*.json yarn.lock ./ COPY package*.json yarn.lock ./
# Install dependencies in /app # Install Node.js dependencies
RUN yarn install --network-timeout 1000000 RUN yarn install --network-timeout 1000000
# Copy the rest of our Next.js folder into /app # Copy the rest of the Next.js folder into /app
COPY . . COPY . .
# Build the Next.js application # Build the Next.js application
RUN yarn build RUN yarn build
# Second stage: Runtime environment
FROM node:18.13.0-alpine
# Copy the virtual environment from the builder stage
COPY --from=builder /venv /venv
ENV PATH="/venv/bin:$PATH"
# Set the working directory
WORKDIR /app
# Copy built assets from the builder stage
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/public ./public
# Ensure port 3000 is accessible to our system # Ensure port 3000 is accessible to our system
EXPOSE 3000 EXPOSE 3000