Dockerfile
Rama main · réplica de lectura del repositorio original.
# =============================================================================
# FlintTrade — Multi-stage Production Dockerfile
# =============================================================================
#
# Build: docker build -t flinttrade:latest .
# Run: docker run -d -p 5100:5100 flinttrade:latest
# (add --env-file .env only if you keep a dev/server .env — none is required)
#
# This image is the backend API only. The React terminal is NOT built here:
# .dockerignore excludes packages/apps/terminal/dist, so port 5100 serves no
# UI from this image. In docker-compose the one-shot `terminal` service builds
# the UI into the terminal_dist volume and Nginx serves it — Nginx is the UI
# origin for Docker deployments.
#
# Uses uv (10x faster than pip) for dependency installation in the builder
# stage, then copies only the installed packages to a minimal runtime image.
# =============================================================================
# ---------------------------------------------------------------------------
# Stage 1: Builder — install Python dependencies with uv
# ---------------------------------------------------------------------------
FROM ghcr.io/astral-sh/uv:python3.14-trixie-slim AS builder
WORKDIR /app
# Install dependencies first (layer cache optimisation).
# SC-07: hash-verified install only — requirements.lock is the uv-exported,
# fully-hashed runtime lockfile; --require-hashes refuses any unpinned/tampered
# wheel. (requirements.txt is the loose dev input, never installed in prod.)
RUN apt-get update \
&& apt-get install -y --no-install-recommends git \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.lock broker-sdk-build.lock broker-sdk-git-requirements.txt brokers.lock ./
COPY scripts/broker_sdk_environment.py scripts/broker_sdk_environment.py
RUN uv pip install --system --no-cache --require-hashes --only-binary=growwapi -r requirements.lock
RUN python scripts/broker_sdk_environment.py repair
# ---------------------------------------------------------------------------
# Stage 2: Runtime — minimal image with only what we need
# ---------------------------------------------------------------------------
FROM python:3.14-slim-trixie AS runtime
# Install runtime dependencies: curl (health checks), tini (init system)
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl tini \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN groupadd -r flinttrade && useradd -r -g flinttrade -m flinttrade
WORKDIR /app
# Copy installed Python packages from builder
COPY --from=builder /usr/local/lib/python3.14/site-packages /usr/local/lib/python3.14/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
# Copy application code
COPY packages/ packages/
COPY VERSION pyproject.toml pnpm-workspace.yaml brokers.lock ./
COPY .env.example .env.example
# Copy entrypoint script
COPY infra/docker/start.sh /app/start.sh
RUN chmod +x /app/start.sh
# Create data directories with correct ownership
RUN mkdir -p /data/flinttrade/audit \
/data/flinttrade/logs \
/data/flinttrade/strategies \
/home/flinttrade/.flinttrade \
&& chown -R flinttrade:flinttrade /data/flinttrade \
&& chown -R flinttrade:flinttrade /home/flinttrade/.flinttrade \
&& chown -R flinttrade:flinttrade /app
# Environment
ENV PYTHONUNBUFFERED=1
ENV AUDIT_LOG_DIR=/data/flinttrade/audit
ENV FLINTTRADE_BACKEND_PORT=5100
ENV PYTHONPATH=/app/packages/core/core/src:/app/packages/core/data/src:/app/packages/core/historical/src:/app/packages/core/indicators/src:/app/packages/services/backtest/src:/app/packages/services/engine/src:/app/packages/services/screener/src:/app/packages/services/journal/src:/app/packages/services/ai/src:/app/packages/services/ditto/src:/app/packages/services/automation/src:/app/packages/integrations/gateway/src:/app/packages/integrations/webhooks/src
# Expose backend port
EXPOSE 5100
# Switch to non-root user
USER flinttrade
# Use tini as init system for proper signal handling (PID 1 reaping)
ENTRYPOINT ["tini", "--"]
CMD ["./start.sh"]