Ctrl K
ComunidadGuías…

Dockerfile

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# nextrmnl as a single container.
#
# Two stages: the interface is built first, then only the finished files go into the image. Node and
# node_modules stay out; at runtime FastAPI serves the built files itself.

# --- Stage 1: build the interface ------------------------------------------------------------------
#
# --platform=$BUILDPLATFORM: the image is built for amd64 and arm64. Without it this stage would run under
# emulation too, and "npm ci" under emulated ARM is very slow. Only /build/dist moves on from here.
FROM --platform=$BUILDPLATFORM node:22-alpine AS interface

WORKDIR /build

COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci

COPY frontend/ ./
RUN npm run build


# --- Stage 2: runtime ------------------------------------------------------------------------------
FROM python:3.13-slim

ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    NEXTRMNL_DATA_DIR=/data \
    NEXTRMNL_FRONTEND_DIST=/app/static

WORKDIR /app

# curl for the healthcheck, gosu to drop root at start.
RUN apt-get update \
    && apt-get install -y --no-install-recommends curl gosu \
    && rm -rf /var/lib/apt/lists/*

COPY backend/requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY backend/app ./app
COPY --from=interface /build/dist ./static

# The user nextrmnl runs as. The container starts as root and drops the rights in the entrypoint.
RUN useradd --system --create-home --uid 1000 nextrmnl \
    && mkdir -p /data \
    && chown -R nextrmnl:nextrmnl /data /app

COPY docker/entrypoint.sh /entrypoint.sh
# Strips Windows line endings: checked out on Windows the script would not start otherwise.
RUN sed -i 's/\r$//' /entrypoint.sh && chmod +x /entrypoint.sh

VOLUME ["/data"]
EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
    CMD curl -fsS "http://127.0.0.1:${NEXTRMNL_PORT:-8000}/api/health" || exit 1

# One worker: SQLite, the open vaults live in this process, and a WebSocket session belongs to one process.
ENTRYPOINT ["/entrypoint.sh"]
# --no-proxy-headers: which proxies may speak for a sender, and say https, is decided by NEXTRMNL_TRUSTED_PROXIES
# inside the app and by nothing else (uvicorn on its own would believe 127.0.0.1), so that nobody is trusted
# from the start and nobody can dodge the sign-in brake with a made-up X-Forwarded-For.
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--workers", "1", "--no-proxy-headers"]