Files
bikoret/deploy/docker/Dockerfile.vav_pipeline
Scott KarpandClaude Fable 5.1 c0d0555aed the name: Bikoret — code, contracts, images
Headers X-Bikoret-Key / -Rebuke / -Verdict / -Bedikah; the `bikoret`
object and the "— bikoret …" fringe on a gate reply; environment
variables BIKORET_*; the image user and paths (/home/bikoret,
/tmp/bikoret, /var/lib/bikoret/manna, /etc/bikoret/secrets,
/opt/bikoret/spec); the tmp-bikoret pod volume; local databases
bikoret_dev/_test. Kubernetes resource names, the shorashim_app role and
the domain are unchanged (Tamid §1.1, "the names that still carry the
old word"). Doorpost c963c4fe…. Elixir 604/0, L3 10/0, korban 295,
Prolog bedikah 44/44. Gitea repo renamed heaviness510/bikoret (old URL
redirects).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-13 22:13:36 +00:00

139 lines
5.5 KiB
Docker

# check=skip=FromPlatformFlagConstDisallowed
# ^ The --platform=linux/amd64 pins below are DELIBERATE (Exoscale SKS
# nodes are amd64). BuildKit lints a constant --platform as a smell;
# here it is the fix. Silenced so a real warning is not lost in noise.
# Bikoret Vav Pipeline — Elixir/OTP release with Sanhedrin
# Construction spec §1.1: Elixir 1.16.1, OTP 26.2.1
# The pipeline and Sanhedrin run in the same BEAM VM.
#
# PLATFORM PIN:
# Both FROM directives below pin `--platform=linux/amd64`. Exoscale
# SKS nodes are amd64; without this pin, a build on an Apple Silicon
# workstation would emit an arm64 image that the cluster cannot exec
# (the kohen's Day 3 fails with "exec format error"). The pin makes
# the build artifact self-correct regardless of build host.
# Local multi-arch dev (linux/amd64,linux/arm64) is supported by
# scripts/build_and_push.sh — see that script for the canonical build.
# === BUILD STAGE ===
FROM --platform=linux/amd64 hexpm/elixir:1.16.1-erlang-26.2.1-ubuntu-jammy-20240125 AS build
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Copy Sanhedrin (Erlang dep, referenced as path dep from vav_pipeline)
COPY sanhedrin/ sanhedrin/
# Copy Vav Pipeline
COPY vav_pipeline/ vav_pipeline/
WORKDIR /app/vav_pipeline
# Fetch deps and compile in prod mode
ENV MIX_ENV=prod
# EMULATED-BUILD JIT WORKAROUND — see the incident note at the top of
# this file. +JMsingle makes the BEAM JIT use a SINGLE writable/
# executable mapping for generated machine code instead of the default
# dual W^X mapping. The dual mapping is what dies (SIGSEGV, exit 139)
# when this amd64 stage runs emulated inside BuildKit's sandbox on an
# Apple Silicon host. Build-stage only: it does not appear in the
# runtime stage, so the shipped release runs with the ordinary
# dual-mapping JIT on the amd64 cluster node.
ENV ERL_FLAGS="+JMsingle true"
RUN mix local.hex --force && \
mix local.rebar --force && \
mix deps.get --only prod && \
mix compile
# Build OTP release
RUN mix release
# === RUNTIME STAGE ===
FROM --platform=linux/amd64 ubuntu:jammy-20240125
# libgmp10 is here for the SHORESH ENGINE, not for the BEAM.
# VavPipeline.ShoreshEnginePort spawns the Haskell binary as an Erlang
# Port — a child process of THIS container (deployment.yaml stages the
# binary onto the shoresh-bin volume with an init container). GHC-built
# executables link libgmp; without it the spawn dies with
# error while loading shared libraries: libgmp.so.10
# and Bikoret runs with no root activation, no te'amim parsing and no
# gematria while still reporting itself healthy.
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libstdc++6 libgmp10 openssl ca-certificates locales && \
rm -rf /var/lib/apt/lists/* && \
sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
locale-gen
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
# Non-root user — the system serves, it does not own
RUN useradd --create-home --shell /bin/bash bikoret
USER bikoret
WORKDIR /home/bikoret
# Copy the release
COPY --from=build --chown=bikoret:bikoret \
/app/vav_pipeline/_build/prod/rel/vav_pipeline ./app
# L1 Torah filesystem — baked into the image (read-only, ~29MB)
# The scroll is sealed in the aron. It ships with the vessel.
# L1 is read-only in fact, not only in name. Until 2026-10-04 the scroll
# was copied in owned by the service user with its write bits on: the
# process that reads Torah could also have rewritten it, and only the
# SHA-256 check would have noticed afterwards. Owned by root, no write
# bit for anyone; the service user can read and traverse, nothing more.
USER root
COPY --chown=root:root l1/ /mnt/torah/
RUN chmod -R a-w,a+rX /mnt/torah
# The second scroll (bishe'arecha §IV): the mesorah snapshot, read-only like L1.
COPY --chown=root:root mesorah/ /mnt/mesorah/
RUN chmod -R a-w,a+rX /mnt/mesorah
USER bikoret
# === INSCRIBE THE DOORPOST ===
# Devarim 11:20 — ukhtavtam al mezuzot beitecha uvish'arecha. A running
# pod IS a threshold, and VavPipeline.Doorpost exists to prove that the
# corporate text at THIS threshold is the same corporate text the system
# was built to hold. It cannot prove that against files it does not have.
#
# The @spec_files set (see vav_pipeline/lib/vav_pipeline/doorpost.ex)
# is inscribed here at the repo-relative paths the module hashes, rooted
# at :doorpost_repo_root from config/prod.exs. Copying whole directories
# rather than 23 individual files means a spec file added to @spec_files
# under specs/, talmudic_engine/src/halt/, or .../middot/ is carried
# automatically instead of silently going :missing in production.
#
# The hash over these files must equal Doorpost.expected_hash(); if it
# does not, this image was built from a tree whose specs and witness
# disagreed, and the pod says so at startup.
COPY --chown=bikoret:bikoret BUILD_AZAZEL.md BUILD_KORBAN.md \
/opt/bikoret/spec/
COPY --chown=bikoret:bikoret specs/ /opt/bikoret/spec/specs/
COPY --chown=bikoret:bikoret talmudic_engine/src/halt/ \
/opt/bikoret/spec/talmudic_engine/src/halt/
COPY --chown=bikoret:bikoret talmudic_engine/src/middot/ \
/opt/bikoret/spec/talmudic_engine/src/middot/
# L1 mount point
ENV L1_MOUNT_POINT=/mnt/torah
ENV MESORAH_MOUNT_POINT=/mnt/mesorah
# Manna provision file location
ENV MANNA_PROVISION_FILE=/var/lib/bikoret/manna/today.json
# PostgreSQL connection for L3
# Set DATABASE_URL in production deployment
# ENV DATABASE_URL=
# Health check port
EXPOSE 4000
CMD ["./app/bin/vav_pipeline", "start"]