# --- BASE --- FROM node:20-slim AS base # Installe deps système pour better-sqlite3 (compilation native) RUN apt-get update && apt-get install -y --no-install-recommends \ python3 make g++ sqlite3 libsqlite3-dev \ && rm -rf /var/lib/apt/lists/* WORKDIR /usr/src/app # --- DEPENDENCIES (Layer mis en cache si package.json/lock inchangés) --- FROM base AS deps # Copie SEULEMENT les manifests COPY package*.json ./ # STRATÉGIE ROBUSTE : # 1. Si package-lock.json existe -> npm ci (rapide, reproductible, sécurisé) # 2. Sinon -> npm install --omit=dev (génère le lock, installe prod) # '--prefer-offline' évite de re-télécharger si cache présent RUN if [ -f package-lock.json ]; then \ echo ">> Lockfile trouvé : npm ci --omit=dev --prefer-offline"; \ npm ci --omit=dev --prefer-offline --no-audit --no-fund; \ else \ echo ">> ATTENTION: package-lock.json MANQUANT. Génération via npm install..."; \ npm install --omit=dev --prefer-offline --no-audit --no-fund; \ fi # --- BUILD / SOURCE --- FROM base AS runner ENV NODE_ENV=production \ PORT=7860 \ DB_PATH=/data/db.sqlite \ UPLOAD_DIR=/data/uploads # Crée user non-root 'node' (déjà dans node:20-slim) et dossiers data RUN mkdir -p /data/uploads /data/db && chown -R node:node /data /usr/src/app WORKDIR /usr/src/app USER node # Copie les deps installées (depuis stage 'deps') AVANT le code source # -> Si tu changes seulement index.html, pas de réinstall npm ! COPY --from=deps --chown=node:node /usr/src/app/node_modules ./node_modules # Copie le code source COPY --chown=node:node . . EXPOSE 7860 # Healthcheck optionnel (HF l'utilise pour "Sleep" mode) HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ CMD node -e "require('http').get('http://localhost:7860/healthz', (r) => {if(r.statusCode!==200) process.exit(1)})" || exit 1 CMD [ "node", "server.js" ]