Docs / Validate documentation (push) Canceled after 0s
Docs / Deploy GitHub Pages (push) Canceled after 0s
CI Final Summary (AI) / AI Final Summary (push) Canceled after 0s
CI Final Summary (AI) / Push/PR event feed (push) Canceled after 0s
CI / CI Integrity and Change Classification (push) Canceled after 0s
CI / Code Quality & Tests (push) Canceled after 0s
Dependency Lock & Migration Safety / Dependency drift (lock vs pyproject) (push) Canceled after 0s
Dependency Lock & Migration Safety / Migration safety (fail-loud + version postconditions) (push) Canceled after 0s
JS Tests / Frontend JS Unit Tests (push) Canceled after 0s
Security / CodeQL Analysis (push) Canceled after 0s
Security / Trivy Vulnerability Scan (push) Canceled after 0s
Tests (OS Matrix) / Py Tests (macos-latest) (push) Canceled after 0s
Tests (OS Matrix) / Py Tests (windows-latest) (push) Canceled after 0s
CI / Extended Validation (Tier 2) (push) Canceled after 0s
CI / Heavy CI (database-provider) (push) Canceled after 0s
CI / Heavy CI (e2e) (push) Canceled after 0s
CI / Heavy CI (integration) (push) Canceled after 0s
CI / Heavy CI (model-validation) (push) Canceled after 0s
CI / Heavy CI (research-backtest) (push) Canceled after 0s
CI / Aggregate CI Results (push) Canceled after 0s
Full project import for the self-hosted code hosting (https://code.aifunny.ltd/gavindiaz/my-NexusTradingForexBot.git). Includes the live-freshness + scaler-hash fixes for the permanent STALE dashboard (tick_pipeline now_utc stamps; infer_probabilities computes model_input_hash on the actual scaled 70D tensor), the data-fetch default-path fix, the g29 web-auth test fixes, and a Chinese user manual (使用手册.md) for the web dashboard. Scratch diagnostic scripts (check*.py, contain a live web-auth token) and the .kilo/ agent-worktree directory are gitignored, not committed. Co-Authored-By: Claude Code <noreply@anthropic.com>
123 lines
5.3 KiB
Docker
123 lines
5.3 KiB
Docker
# ============================================================
|
|
# Nexus Scalp Engine — Multi-stage Docker image
|
|
# ============================================================
|
|
# Stage 1 builder : deps wheel build (cached independently of src/)
|
|
# Stage 2 runtime : minimal image, non-root user, no build toolchain
|
|
#
|
|
# FIXLOG (2026-09-09, docker-repair):
|
|
# 1. Builder previously re-resolved the project via PEP 517 with
|
|
# --find-links=/wheels as the ONLY index ("--no-index"); the isolated
|
|
# build env then tried to fetch "wheel" from /wheels and died with
|
|
# "No matching distribution found for wheel". Fixed with
|
|
# --no-build-isolation (setuptools+wheel are preinstalled in the same
|
|
# RUN, so no isolation is needed and nothing is re-fetched).
|
|
# 2. torch 2.14.0 on Linux pulls the full CUDA-13 wheel family
|
|
# (~5.5 GB installed). The engine's live serving path is CPU-only
|
|
# (torch.load(map_location="cpu"), torch.set_num_threads(1), no
|
|
# .cuda()/device usage anywhere in src/nexus_scalp), so the image now
|
|
# installs torch from the official CPU index. Image drops ~5.5 GB ->
|
|
# ~1.2 GB and build time drops proportionally. Windows/training hosts
|
|
# are unaffected: requirements.txt (CUDA build) remains the source of
|
|
# truth outside Docker.
|
|
# ============================================================
|
|
|
|
# ============================================================
|
|
# Stage 1: build dependencies (cached via pyproject+requirements)
|
|
# ============================================================
|
|
FROM python:3.11-slim AS builder
|
|
|
|
WORKDIR /build
|
|
|
|
ENV PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
PIP_NO_CACHE_DIR=1 \
|
|
PIP_DISABLE_PIP_VERSION_CHECK=1
|
|
|
|
# System build deps for torch/polars wheels.
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
build-essential \
|
|
gcc \
|
|
curl \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# CPU-only torch index (see FIXLOG note 2).
|
|
ARG PIP_EXTRA_INDEX_URL=https://download.pytorch.org/whl/cpu
|
|
ENV PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}
|
|
|
|
# Dependency layer: copy only the manifests so this layer reuses the
|
|
# Docker cache unless requirements actually change.
|
|
COPY pyproject.toml requirements.txt README.md ./
|
|
COPY src/ ./src/
|
|
|
|
RUN pip install --upgrade pip setuptools wheel \
|
|
&& pip wheel --wheel-dir=/wheels --no-cache-dir . \
|
|
&& mkdir -p /install \
|
|
&& pip install --no-index --find-links=/wheels --prefix=/install --no-build-isolation . \
|
|
# The runtime stage does NOT mount /install into sys.path (PYTHONPATH only
|
|
# carries /app/src), so the dependency tree must live where the interpreter
|
|
# looks: /usr/local/lib/python3.11/site-packages. A --prefix=/install copy
|
|
# is only reachable via PYTHONPATH, which caused ModuleNotFoundError: typer
|
|
# in the entrypoint's `db migrate` gate (docker-repair, 2026-09-09).
|
|
&& mkdir -p /layerdeps \
|
|
&& cp -a /install/lib/python3.11/site-packages/. /layerdeps/
|
|
|
|
# ============================================================
|
|
# Stage 2: lightweight runtime (non-root)
|
|
# ============================================================
|
|
FROM python:3.11-slim AS runner
|
|
|
|
WORKDIR /app
|
|
|
|
ENV PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
PIP_NO_CACHE_DIR=1 \
|
|
PYTHONPATH="/app/src:/install/lib/python3.11/site-packages" \
|
|
PATH="/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/install/bin" \
|
|
TZ=UTC \
|
|
NSE_WEB_HOST=0.0.0.0
|
|
# NSE_WEB_HOST=0.0.0.0: containers must bind the API on all interfaces or the
|
|
# `docker -p` port mapping reaches nothing (engine default is 127.0.0.1 inside
|
|
# the container -> host curl gets connection reset; docker-repair 2026-09-09).
|
|
|
|
# libgomp1: required at runtime by torch/polars native libs (CPU wheels do
|
|
# not vendor it, debian-slim does not ship it) — the engine failed to boot
|
|
# with OSError "libgomp.so.1: cannot open shared object file" without it.
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
curl \
|
|
ca-certificates \
|
|
tzdata \
|
|
libgomp1 \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
RUN groupadd -g 10001 appgroup && \
|
|
useradd -u 10001 -g appgroup -s /bin/sh -m appuser
|
|
|
|
COPY --from=builder /layerdeps/ /usr/local/lib/python3.11/site-packages/
|
|
COPY configs/ configs/
|
|
COPY docker/ docker/
|
|
COPY src/ src/
|
|
COPY Web/ Web/
|
|
|
|
RUN chmod +x /app/docker/*.sh \
|
|
&& mkdir -p /app/artifacts/models /app/artifacts/logs /app/data /app/Web \
|
|
# live.yaml is operator-local (gitignored, never baked): the container CMD
|
|
# and docs/docker.md both reference configs/live.yaml, so ship the example
|
|
# under the canonical name (env vars remain the real bootstrap knobs —
|
|
# docker-repair 2026-09-09: image previously shipped no live.yaml at all
|
|
# and the engine died with "Config missing: configs/live.yaml").
|
|
&& cp /app/configs/live.yaml.example /app/configs/live.yaml \
|
|
&& chown -R appuser:appgroup /app \
|
|
&& chmod -R u+w /app/artifacts /app/data
|
|
|
|
USER appuser
|
|
|
|
EXPOSE 9090
|
|
|
|
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=6 \
|
|
CMD ["/app/docker/healthcheck.sh"]
|
|
|
|
# The entrypoint handles env validation, dir bootstrap, migrations and
|
|
# startup summary; the CMD is the default engine command (PAPER mode).
|
|
ENTRYPOINT ["/app/docker/entrypoint.sh"]
|
|
CMD ["python", "-m", "nexus_scalp.cli.main", "start", "--mode", "paper", "--config", "configs/live.yaml", "--port", "9090"]
|