From 2a815c92e6da9cceb9633fb5b96086897a245c35 Mon Sep 17 00:00:00 2001 From: orangecoding Date: Wed, 10 Dec 2025 13:23:17 +0100 Subject: [PATCH] reduce docker image size --- .dockerignore | 44 +++++++++++++++++++++++++++++-- Dockerfile | 66 +++++++++++++++++++++++++++++++++------------- docker-compose.yml | 14 +++++----- package.json | 2 +- 4 files changed, 99 insertions(+), 27 deletions(-) diff --git a/.dockerignore b/.dockerignore index b40cae6..740a20b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,47 @@ +# Dependencies (will be installed fresh in container) node_modules/ -npm-debug.log -test/ + +# Database and config (mounted as volumes) db/ conf/ + +# Git .git/ .github/ +.gitignore + +# IDE and editor +.idea/ +.vscode/ +*.swp +*.swo +.DS_Store + +# Testing +test/ + +# Documentation +doc/ +*.md +!README.md + +# Development config files +.babelrc +.husky/ +.nvmrc +.prettierrc +.prettierignore +eslint.config.js + +# Docker files (not needed inside container) +Dockerfile +docker-compose.yml +docker-test.sh +.dockerignore + +# Logs +*.log +npm-debug.log + +# Build artifacts (built fresh in container) +dist/ diff --git a/Dockerfile b/Dockerfile index a9ef1b2..198e9e5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,58 @@ -FROM node:22-slim +# ================================ +# Stage 1: Build stage +# ================================ +FROM node:22-alpine AS builder + +WORKDIR /build + +# Install build dependencies needed for native modules (better-sqlite3) +RUN apk add --no-cache python3 make g++ + +# Copy package files first for better layer caching +COPY package.json yarn.lock ./ + +# Install all dependencies (including devDependencies for building) +RUN yarn config set network-timeout 600000 \ + && yarn --frozen-lockfile + +# Copy source files needed for build +COPY index.html vite.config.js ./ +COPY ui ./ui +COPY lib ./lib + +# Build frontend assets +RUN yarn build:frontend + +# ================================ +# Stage 2: Production stage +# ================================ +FROM node:22-alpine WORKDIR /fredy -# Install Chromium and curl without extra recommended packages and clean apt cache -# curl is needed for the health check -RUN apt-get update \ - && apt-get install -y --no-install-recommends chromium curl \ - && rm -rf /var/lib/apt/lists/* +# Install Chromium and curl (for healthcheck) +# Using Alpine's chromium package which is much smaller +RUN apk add --no-cache chromium curl ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \ - PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium + PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser -# Copy lockfiles first to leverage cache for dependencies -COPY package.json yarn.lock . +# Install build dependencies for native modules, then remove them after yarn install +COPY package.json yarn.lock ./ -# Set Yarn timeout, install dependencies and PM2 globally -RUN yarn config set network-timeout 600000 \ - && yarn --frozen-lockfile \ - && yarn global add pm2 +RUN apk add --no-cache --virtual .build-deps python3 make g++ \ + && yarn config set network-timeout 600000 \ + && yarn --frozen-lockfile --production \ + && yarn cache clean \ + && apk del .build-deps -# Copy application source and build production assets -COPY . . -RUN yarn build:frontend +# Copy built frontend from builder stage +COPY --from=builder /build/ui/public ./ui/public + +# Copy application source (only what's needed at runtime) +COPY index.js ./ +COPY index.html ./ +COPY lib ./lib # Prepare runtime directories and symlinks for data and config RUN mkdir -p /db /conf \ @@ -34,5 +65,4 @@ EXPOSE 9998 VOLUME /db VOLUME /conf -# Start application using PM2 runtime -CMD ["pm2-runtime", "index.js"] +CMD ["node", "index.js"] diff --git a/docker-compose.yml b/docker-compose.yml index a02e717..91499e4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,22 +1,24 @@ services: fredy: container_name: fredy - # build from empty build folder to reduce size of image build: context: . dockerfile: Dockerfile image: ghcr.io/orangecoding/fredy - # map existing config and database volumes: - ./conf:/conf - ./db:/db ports: - "9998:9998" restart: unless-stopped + # Resource limits to prevent runaway memory usage from Chromium + deploy: + resources: + limits: + memory: 1G healthcheck: - # The container will immediately stop when health check fails after retries - test: ["CMD-SHELL", "curl --fail --silent --show-error --max-time 5 http://localhost:9998/ || exit 1"] + test: ["CMD", "curl", "--fail", "--silent", "--show-error", "--max-time", "5", "http://localhost:9998/"] interval: 120s timeout: 10s - retries: 1 - start_period: 10s + retries: 3 + start_period: 30s diff --git a/package.json b/package.json index 05e5e78..573e3f7 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fredy", - "version": "15.1.0", + "version": "15.1.1", "description": "[F]ind [R]eal [E]states [d]amn eas[y].", "scripts": { "prepare": "husky",