From 52e5a607248eb8f93d87553d784479184dd77e98 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 23:02:48 -0600 Subject: [PATCH] refactor(docker): streamline multi-stage build process and optimize dependencies --- Dockerfile | 66 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5e23181..275e1e4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,46 +3,54 @@ ARG NODE_HASH=sha256:0340fa682d72068edf603c305bfbc10e23219fb0e40df58d9ea4d6f33a9 ARG PYTHON_IMAGE=python:3.13-alpine ARG PYTHON_HASH=sha256:e7e041128ffc3e3600509f508e44d34ab08ff432bdb62ec508d01dfc5ca459f7 +# Stage 1: Build Frontend FROM ${NODE_IMAGE}@${NODE_HASH} AS build-frontend - WORKDIR /src - -COPY package.json vite.config.js tailwind.config.js postcss.config.js ./ -COPY pnpm-lock.yaml ./ +COPY package.json pnpm-lock.yaml vite.config.js tailwind.config.js postcss.config.js ./ COPY meshchatx/src/frontend ./meshchatx/src/frontend - -RUN corepack enable && corepack prepare pnpm@latest --activate - -RUN pnpm install --frozen-lockfile && \ +RUN corepack enable && corepack prepare pnpm@latest --activate && \ + pnpm install --frozen-lockfile && \ pnpm run build-frontend +# Stage 2: Build Backend & Virtual Environment +FROM ${PYTHON_IMAGE}@${PYTHON_HASH} AS builder +WORKDIR /build +# Install build dependencies for C-extensions +RUN apk add --no-cache gcc musl-dev linux-headers python3-dev libffi-dev openssl-dev +# Setup venv and install dependencies +RUN python -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" +COPY pyproject.toml poetry.lock ./ +RUN pip install --no-cache-dir poetry setuptools wheel && \ + poetry config virtualenvs.create false && \ + poetry install --no-root --only main + +# Copy source code and built frontend +COPY meshchatx ./meshchatx +COPY --from=build-frontend /src/meshchatx/public ./meshchatx/public + +# Install the package itself into the venv +RUN pip install . && \ + # Trigger LXST filter compilation while build tools are still present + python -c "import LXST.Filters; print('LXST Filters compiled successfully')" && \ + python -m compileall /opt/venv/lib/python3.13/site-packages + +# Stage 3: Final Runtime Image FROM ${PYTHON_IMAGE}@${PYTHON_HASH} - WORKDIR /app - -RUN apk add --no-cache ffmpeg espeak-ng opusfile libffi-dev su-exec py3-setuptools && \ +# Install runtime dependencies only +# We keep py3-setuptools because CFFI/LXST might need it at runtime on Python 3.12+ +RUN apk add --no-cache ffmpeg espeak-ng opusfile libffi su-exec py3-setuptools && \ addgroup -g 1000 meshchat && adduser -u 1000 -G meshchat -S meshchat && \ mkdir -p /config && chown meshchat:meshchat /config -COPY pyproject.toml poetry.lock ./ -RUN apk add --no-cache --virtual .build-deps \ - gcc \ - musl-dev \ - linux-headers \ - python3-dev && \ - pip install --no-cache-dir poetry setuptools && \ - poetry config virtualenvs.create false && \ - poetry install --no-root --only main && \ - # Trigger LXST filter compilation while build tools are still present - # We use a more thorough approach to ensure compilation completes - python -c "import LXST; import LXST.Filters" || true && \ - python -m compileall /usr/local/lib/python3.13/site-packages && \ - apk del .build-deps - -COPY --chown=meshchat:meshchat meshchatx ./meshchatx -COPY --from=build-frontend --chown=meshchat:meshchat /src/meshchatx/public ./meshchatx/public +# Copy the virtual environment from the build stage +COPY --from=builder --chown=meshchat:meshchat /opt/venv /opt/venv +# Set up environment +ENV PATH="/opt/venv/bin:$PATH" ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1 -CMD ["sh", "-c", "chown -R meshchat:meshchat /config && exec su-exec meshchat python -m meshchatx.meshchat --host=0.0.0.0 --reticulum-config-dir=/config/.reticulum --storage-dir=/config/.meshchat --headless"] +# Run the app using the installed 'meshchat' entrypoint +CMD ["sh", "-c", "chown -R meshchat:meshchat /config && exec su-exec meshchat meshchat --host=0.0.0.0 --reticulum-config-dir=/config/.reticulum --storage-dir=/config/.meshchat --headless"]