# Image du service en ligne BacktestStudio : une seule image pour Railway et pour un VPS (docker-compose.yml).
# Construire depuis la racine du projet (contexte = racine, exclusions dans /.dockerignore) :
#   docker build -f deploy/Dockerfile -t bts .
# Railway : variable de service RAILWAY_DOCKERFILE_PATH=deploy/Dockerfile (voir deploy/README.md, §Railway).
#
# Données : un seul montage /data (Railway n'accepte qu'un volume par service), monté en root.
# Le script de démarrage crée les sous-dossiers, donne le volume à l'utilisateur « node » puis abandonne
# les privilèges : ni le serveur ni la sandbox Pine ne tournent en root. Pas d'instruction VOLUME ni USER ici.

# Node 22.23.5 (≥ 22.18 exigé : TypeScript exécuté sans compilation), Debian 12, index multi-architecture épinglé.
FROM node:22.23.5-bookworm-slim@sha256:e9f565d32859f0cbfb52125eafe8be39390f24dac302dc3cdf566e8ba3ab21ee

# tini : PID 1 (lancé par le script de démarrage, déjà non root) qui relaie SIGTERM à Node et récupère les orphelins.
# setpriv (util-linux, déjà présent dans l'image) sert à abandonner les privilèges.
RUN apt-get update \
 && apt-get install -y --no-install-recommends tini \
 && rm -rf /var/lib/apt/lists/*

ENV NODE_ENV=production \
    HOST=0.0.0.0 \
    PORT=8080 \
    BTS_DATA_DIR=/data/data \
    BTS_REPORTS_DIR=/data/reports \
    BTS_DB=/data/data/bts.db \
    BTS_STRATEGIES_DIR=/data/data/strategies \
    BTS_NO_OPEN=1 \
    BTS_POOL_SIZE=2 \
    BTS_SANDBOX_MAX_MB=768 \
    BTS_JOBS_CONCURRENCY=2
# Les trois dernières valeurs sont un plancher prudent (sans elles, le pool se règle sur les processeurs de l'hôte,
# pas du conteneur) ; les variables du service Railway les remplacent. Référence : docs/notes/variables-production.md.

WORKDIR /app

# Dépendances de production seulement (couche mise en cache tant que package-lock.json ne change pas).
COPY package.json package-lock.json ./
RUN npm ci --omit=dev --no-audit --no-fund && npm cache clean --force && rm -rf /root/.npm /tmp/*

# Code : liste fermée (aucun document interne). docs/ et deploy/ sont publiés par /source (AGPL).
# Polices Geist (src/core/ui/fonts) et build ECharts (src/core/report/vendor) sont dans src/ : copiées au démarrage
# dans <BTS_REPORTS_DIR>/_assets par ensureReportAssets.
COPY tsconfig.json README.md LICENSE COPYING ./
COPY tools/build-echarts.mjs ./tools/build-echarts.mjs
COPY src ./src
COPY docs/legal ./docs/legal
COPY docs/notes/renommage-backteststudio.md docs/notes/variables-production.md ./docs/notes/
COPY docs/CONCEPTION.md ./docs/CONCEPTION.md
COPY deploy/Dockerfile deploy/docker-entrypoint.sh deploy/docker-compose.yml deploy/Caddyfile \
     deploy/litestream.yml deploy/env.example deploy/README.md ./deploy/

# Code en lecture seule pour l'utilisateur du service (propriété root), script de démarrage exécutable.
RUN chmod 0755 /app/deploy/docker-entrypoint.sh \
 && mkdir -p /data && chown node:node /data

EXPOSE 8080
# Contrôle de santé Docker (VPS) ; Railway l'ignore et utilise healthcheckPath (/healthz).
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
  CMD ["setpriv", "--reuid=node", "--regid=node", "--clear-groups", "node", "-e", "fetch('http://127.0.0.1:'+(process.env.PORT||8080)+'/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]

STOPSIGNAL SIGTERM
ENTRYPOINT ["/app/deploy/docker-entrypoint.sh"]
CMD ["node", "--disable-warning=ExperimentalWarning", "src/web/server.ts"]
