|
1 | | -# ================================ |
2 | | -# Stage 1: Build stage |
3 | | -# ================================ |
4 | | -FROM node:22-alpine AS builder |
| 1 | +FROM node:22-slim |
| 2 | + |
| 3 | +# System deps for Chrome for Testing + build tools for native modules (better-sqlite3) |
| 4 | +# Must run as root |
| 5 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 6 | + curl ca-certificates fonts-liberation libasound2 \ |
| 7 | + libatk-bridge2.0-0 libatk1.0-0 libcups2 libdbus-1-3 \ |
| 8 | + libdrm2 libgbm1 libgtk-3-0 libnspr4 libnss3 \ |
| 9 | + libx11-xcb1 libxcomposite1 libxdamage1 libxrandr2 xdg-utils \ |
| 10 | + python3 make g++ \ |
| 11 | + && rm -rf /var/lib/apt/lists/* \ |
| 12 | + && mkdir -p /db /conf /fredy \ |
| 13 | + && chown node:node /db /conf /fredy |
5 | 14 |
|
6 | | -WORKDIR /build |
7 | | - |
8 | | -# Install build dependencies needed for native modules (better-sqlite3) |
9 | | -RUN apk add --no-cache python3 make g++ |
10 | | - |
11 | | -# Copy package files first for better layer caching |
12 | | -COPY package.json yarn.lock ./ |
13 | | - |
14 | | -# Install all dependencies (including devDependencies for building) |
15 | | -RUN yarn config set network-timeout 600000 \ |
16 | | - && yarn --frozen-lockfile |
17 | | - |
18 | | -# Copy source files needed for build |
19 | | -COPY index.html vite.config.js ./ |
20 | | -COPY ui ./ui |
21 | | -COPY lib ./lib |
| 15 | +WORKDIR /fredy |
22 | 16 |
|
23 | | -# Build frontend assets |
24 | | -RUN yarn build:frontend |
| 17 | +# Everything from here runs as the built-in non-root node user (UID 1000) |
| 18 | +USER node |
25 | 19 |
|
26 | | -# ================================ |
27 | | -# Stage 2: Production stage |
28 | | -# ================================ |
29 | | -FROM node:22-alpine |
| 20 | +ENV NODE_ENV=production \ |
| 21 | + IS_DOCKER=true |
30 | 22 |
|
31 | | -WORKDIR /fredy |
| 23 | +COPY --chown=node:node package.json yarn.lock ./ |
32 | 24 |
|
33 | | -# Install Chromium and curl (for healthcheck) |
34 | | -# Using Alpine's chromium package which is much smaller |
35 | | -RUN apk add --no-cache chromium curl |
| 25 | +# Install dependencies and purge build tools (only needed to compile better-sqlite3) |
| 26 | +RUN yarn config set network-timeout 600000 \ |
| 27 | + && yarn --frozen-lockfile \ |
| 28 | + && yarn cache clean |
36 | 29 |
|
37 | | -ENV NODE_ENV=production \ |
38 | | - IS_DOCKER=true \ |
39 | | - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \ |
40 | | - PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser |
| 30 | +# Install Chrome for Testing in a separate layer — it's ~150MB and rarely changes, |
| 31 | +# so keeping it separate avoids re-downloading on every code/dependency change |
| 32 | +RUN npx puppeteer browsers install chrome |
41 | 33 |
|
42 | | -# Install build dependencies for native modules, then remove them after yarn install |
43 | | -COPY package.json yarn.lock ./ |
| 34 | +# Purge build tools now that native modules are compiled |
| 35 | +USER root |
| 36 | +RUN apt-get purge -y python3 make g++ \ |
| 37 | + && apt-get autoremove -y \ |
| 38 | + && rm -rf /var/lib/apt/lists/* |
| 39 | +USER node |
44 | 40 |
|
45 | | -RUN apk add --no-cache --virtual .build-deps python3 make g++ \ |
46 | | - && yarn config set network-timeout 600000 \ |
47 | | - && yarn --frozen-lockfile --production \ |
48 | | - && yarn cache clean \ |
49 | | - && apk del .build-deps |
| 41 | +COPY --chown=node:node index.html vite.config.js ./ |
| 42 | +COPY --chown=node:node ui ./ui |
| 43 | +COPY --chown=node:node lib ./lib |
50 | 44 |
|
51 | | -# Copy built frontend from builder stage |
52 | | -COPY --from=builder /build/ui/public ./ui/public |
| 45 | +RUN yarn build:frontend |
53 | 46 |
|
54 | | -# Copy application source (only what's needed at runtime) |
55 | | -COPY index.js ./ |
56 | | -COPY index.html ./ |
57 | | -COPY lib ./lib |
| 47 | +COPY --chown=node:node index.js ./ |
58 | 48 |
|
59 | | -# Prepare runtime directories and symlinks for data and config |
60 | | -RUN mkdir -p /db /conf \ |
61 | | - && chown 1000:1000 /db /conf \ |
62 | | - && chmod 777 /db /conf \ |
63 | | - && ln -s /db /fredy/db \ |
| 49 | +RUN ln -s /db /fredy/db \ |
64 | 50 | && ln -s /conf /fredy/conf |
65 | 51 |
|
66 | 52 | EXPOSE 9998 |
67 | 53 | VOLUME /db |
68 | 54 | VOLUME /conf |
69 | 55 |
|
| 56 | +HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ |
| 57 | + CMD curl -f http://localhost:9998/ || exit 1 |
| 58 | + |
70 | 59 | CMD ["node", "index.js"] |
0 commit comments