Ctrl K
ComunidadGuías…

Dockerfile.selfhost

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

Archivo original ↗Preguntar a KiBot
FROM rust:bookworm AS backend-builder

# Build backend
RUN echo "Building backend..."

RUN apt-get update && apt-get install -y \
    pkg-config \
    libssl-dev \
    build-essential \
    git \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Caps parallel LLVM instances so this stage fits the image build's memory budget
ENV CARGO_PROFILE_RELEASE_CODEGEN_UNITS=4

COPY backend/Cargo.toml backend/Cargo.lock ./

RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release --locked
RUN rm -rf src target/release/deps/betterlytics* target/release/betterlytics*

COPY backend/src ./src
COPY backend/assets ./assets

RUN cargo build --release --locked

####
# Build dashboard

FROM node:24-slim AS dashboard-builder

# Forces BuildKit to run this stage after the backend build so the two heaviest stages never share peak memory
COPY --from=backend-builder /app/target/release/betterlytics /dev/null

ENV NODE_OPTIONS="--max-old-space-size=4096"

RUN echo "Building dashboard..."
ENV NEXT_TELEMETRY_DISABLED=1
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable && corepack prepare pnpm@10.34.5 --activate

RUN apt-get update -y && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./
COPY dashboard/package.json ./dashboard/
COPY backend/package.json ./backend/
COPY docs/package.json ./docs/
RUN pnpm install --frozen-lockfile --filter dashboard

COPY dashboard/.env.build ./.env
COPY dashboard/prisma ./dashboard/prisma

WORKDIR /app/dashboard

RUN pnpm exec prisma generate

COPY dashboard/ .

RUN pnpm run build

####
# Build initializer

FROM node:24-slim AS initializer-builder

RUN echo "Building initializer..."
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable && corepack prepare pnpm@10.34.5 --activate

WORKDIR /app

COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./
COPY dashboard/package.json ./dashboard/
COPY backend/package.json ./backend/
COPY docs/package.json ./docs/
RUN pnpm install --frozen-lockfile --filter .

####
# Minify static files

FROM node:24-slim AS static-builder

RUN echo "Minifying static files..."
WORKDIR /app
COPY static/analytics.js static/replay.js static/build.mjs ./
RUN node build.mjs . .

####
# Build Caddy
FROM caddy:2.11.4-builder AS caddy-builder
RUN xcaddy build v2.11.4 \
    --with github.com/mholt/caddy-ratelimit@5625512f24f6f59d6f64fb3aafe5eecff0b286db

####
# Runtime image

FROM node:24-slim

RUN echo "Building runtime image..."
RUN apt-get update && apt-get install -y \
    supervisor \
    openssl \
    libssl3 \
    ca-certificates \
    curl \
    gettext-base \
    && rm -rf /var/lib/apt/lists/*

COPY --from=caddy-builder /usr/bin/caddy /usr/bin/caddy
# Caddy runs as root under supervisord; keep certs and the ACME account on the /data volume
ENV XDG_DATA_HOME=/data
ENV XDG_CONFIG_HOME=/config

RUN npm install -g prisma@6.19.3
# The prisma CLI otherwise pings checkpoint.prisma.io on every `prisma migrate deploy` (betterlytics-init runs this image)
ENV CHECKPOINT_DISABLE=1

# Copy backend
RUN echo "Copying backend..."
COPY --from=backend-builder /app/target/release/betterlytics /app/backend/app
COPY --from=backend-builder /app/assets /app/backend/assets

# Copy dashboard
RUN echo "Copying dashboard..."
COPY --from=dashboard-builder /app/dashboard/public /app/dashboard/public
COPY --from=dashboard-builder /app/dashboard/.next/standalone /app/
COPY --from=dashboard-builder /app/dashboard/.next/standalone/worker.js /app/dashboard/worker.js
COPY --from=dashboard-builder /app/dashboard/.next/static /app/dashboard/.next/static

# Copy initializer dependencies
RUN echo "Copying initializer dependencies..."
COPY --from=initializer-builder /app/node_modules /app/initializer/node_modules

# Copy initializer source files
COPY initializer/package.json /app/initializer/
COPY scripts/ /app/initializer/scripts/
COPY migrations/ /app/initializer/migrations/
COPY dashboard/prisma/ /app/initializer/prisma/

# Copy static scripts for Caddy (web-vitals.js ships pre-minified; esbuild would strip its legal banner)
COPY --from=static-builder /app/analytics.min.js /srv/static/analytics.js
COPY --from=static-builder /app/replay.min.js /srv/static/replay.js
COPY static/web-vitals.js /srv/static/web-vitals.js

COPY LICENSE THIRD-PARTY-LICENSES.md /app/

# Startup, proxy and process config. The selfhost compose mounts only /derive.sh.
COPY selfhost/proxy/ /etc/caddy/
COPY selfhost/supervisord.conf /etc/supervisor/conf.d/betterlytics.conf
COPY selfhost/entrypoint.sh selfhost/env.sh selfhost/secrets-env.sh selfhost/healthcheck.sh /app/selfhost/

# Inherited by every container from this image; the selfhost compose disables it for betterlytics-init.
# start-period covers the first HTTPS boot waiting on ACME. --start-interval needs Docker Engine 25.
HEALTHCHECK --interval=30s --timeout=5s --start-period=120s --start-interval=5s --retries=3 \
    CMD ["/bin/sh", "/app/selfhost/healthcheck.sh"]

ENTRYPOINT ["/bin/sh", "/app/selfhost/entrypoint.sh"]
CMD ["run"]

# Bake the release version for the dashboard
ARG APP_VERSION=dev
ENV APP_VERSION=$APP_VERSION