# 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. # Shorashim 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 Shorashim 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 shorashim USER shorashim WORKDIR /home/shorashim # Copy the release COPY --from=build --chown=shorashim:shorashim \ /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. COPY --chown=shorashim:shorashim l1/ /mnt/torah/ # === 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=shorashim:shorashim BUILD_AZAZEL.md BUILD_KORBAN.md \ /opt/shorashim/spec/ COPY --chown=shorashim:shorashim specs/ /opt/shorashim/spec/specs/ COPY --chown=shorashim:shorashim talmudic_engine/src/halt/ \ /opt/shorashim/spec/talmudic_engine/src/halt/ COPY --chown=shorashim:shorashim talmudic_engine/src/middot/ \ /opt/shorashim/spec/talmudic_engine/src/middot/ # L1 mount point ENV L1_MOUNT_POINT=/mnt/torah # Manna provision file location ENV MANNA_PROVISION_FILE=/var/lib/shorashim/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"]