forked from quarto-dev/q2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
149 lines (130 loc) · 8.06 KB
/
Copy pathDockerfile
File metadata and controls
149 lines (130 loc) · 8.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# ══════════════════════════════════════════════════════════════════════
# q2 — single Rust binary, live .qmd rendering
# ══════════════════════════════════════════════════════════════════════
# `q2 notebook serve` runs the full stack:
# lance-graph parser → DataFusion planner → LanceDB
# quarto-core + deno_core (V8 JIT) → live .qmd rendering
# ndarray → SIMD compute
# MCP over SSE with 16 tools
#
# The Palantir cockpit (React/Vite) is embedded into the binary at
# compile time via include_dir!. Routes:
# / → Palantir cockpit with aiwar graph (221 nodes)
# /demo → Infrastructure demo (24 seed nodes)
# /debug → Neural debugger (18,763 functions across 4 repos)
# /mcp/* → MCP endpoints (lance-graph)
#
# Pinned: Rust 1.94.0 | Arrow 57 | DataFusion 51
# ══════════════════════════════════════════════════════════════════════
# ── Stage 1: Build the Vite frontend ─────────────────────────────────
FROM node:22-alpine AS frontend
WORKDIR /build
COPY cockpit/package.json cockpit/package-lock.json ./
RUN npm ci
COPY cockpit/ .
RUN npm run build && ls -la dist/
# ── Stage 2: Build the Rust binary ───────────────────────────────────
FROM debian:bookworm AS builder
RUN apt-get update && apt-get install -y \
git curl build-essential cmake clang \
libssl-dev pkg-config python3 \
protobuf-compiler libprotobuf-dev \
ca-certificates lld \
&& rm -rf /var/lib/apt/lists/*
# Rust 1.94.0
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \
sh -s -- -y --default-toolchain 1.94.0
ENV PATH="/root/.cargo/bin:${PATH}"
WORKDIR /build
# q2 comes from the Railway build context (this repo, this branch)
COPY . /build/q2
# Copy the built Vite frontend into the cockpit/dist/ directory
# so include_dir! can embed it at compile time
COPY --from=frontend /build/dist/ /build/q2/cockpit/dist/
# Pull the big FMA body wire (BSO2) from the q2 release into dist/ so include_dir!
# embeds it and the server serves it SAME-ORIGIN at /body.soa.gz. The browser cannot
# fetch the release URL directly (github.com/.../releases/download sends no CORS
# header on its redirect → "TypeError: Failed to fetch"), so /body fetches the
# same-origin copy. The asset stays in the release (downloaded at build), never git.
# 20260629b re-bake: teeth → skeleton + per-vessel diameter boundary (no stray fat
# branches). Pulled under its stamped name, served same-origin AS body.soa.gz so /body
# picks it up; the old body.soa.gz stays in the release untouched.
RUN curl -fSL https://github.com/AdaWorldAPI/q2/releases/download/fma-body-soa-v3-v1/body.20260629c.soa.gz \
-o /build/q2/cockpit/dist/body.soa.gz \
&& ls -lh /build/q2/cockpit/dist/body.soa.gz
# Same for the /helix wire: one SoA (BSO2 ver 6) = F16 pos + a canonical Signed360
# NORMAL column in the same struct-of-arrays. Same-origin for the same CORS reason;
# named by cockpit/public/body.manifest.json (helix_latest). Stays in the release.
RUN curl -fSL https://github.com/AdaWorldAPI/q2/releases/download/fma-body-soa-v3-v1/body.20260629c.v6helix.soa.gz \
-o /build/q2/cockpit/dist/body.20260629c.v6helix.soa.gz \
&& ls -lh /build/q2/cockpit/dist/body.20260629c.v6helix.soa.gz
# Sibling deps — clone from GitHub
# graph-flow stub is local (crates/stubs/graph-flow), no rs-graph-llm needed
#
# lance-graph + ndarray are cloned at their BRANCH HEAD (latest) — NOT a pinned,
# stale SHA. The repos at their tips are mutually consistent, so "use the latest of
# everything" is the rule: a pinned-old lance-graph (36059ce0) is exactly what
# lacked `guid-v3-tail` and broke the build. The `COPY . /build/q2` above changes on
# every q2 commit, invalidating this RUN layer too, so each build re-clones fresh
# (no stale-cache problem the old pin was guarding against).
#
# Sibling checkouts the path deps resolve against:
# /build/lance-graph → lance-graph @ main HEAD — carries guid-v2-tail +
# guid-v3-tail and the 65-concept ogar_codebook mirror.
# /build/ndarray → the REAL AdaWorldAPI/ndarray fork, consumed by BOTH
# lance-graph (../../../ndarray) AND q2-ndarray
# (../../../../ndarray). `--depth 1` WITHOUT
# --recurse-submodules: ndarray's workspace `exclude`s
# crates/burn, so the burn submodule (AdaWorldAPI/burn.git)
# is never needed — leaving it unfetched is correct.
#
# COUNT_FUSE: lance-graph-ogar asserts (E0080 on mismatch)
# CODEBOOK.len() == ogar_vocab::class_ids::ALL.len(). Both move together at HEAD —
# lance-graph main's 65-concept codebook mirror matches OGAR main's 65-concept vocab;
# q2's Cargo.lock pins ogar-vocab to OGAR main HEAD (a1fb170). Always bump the two
# repos' HEADs together, never one alone.
#
# neo4j-rs is intentionally NOT cloned — a discarded Neo4j-GUI experiment referenced
# by no manifest; the only neo4j path is the opt-in `neo4j-fallback` (crates.io neo4rs).
RUN git clone --depth 1 https://github.com/AdaWorldAPI/lance-graph.git \
&& git clone --depth 1 https://github.com/AdaWorldAPI/ndarray.git
# CPU baseline: x86-64-v4 (the 4th microarch level — AVX-512F/BW/CD/DQ/VL on top
# of v3's AVX2+FMA). This is the compile FLOOR; it flips on `target_feature =
# "avx512f"`, so q2-ndarray's `simd.rs` dispatch selects its native `simd_avx512`
# backend (`__m512`/`__m512d`/`__m512i`) instead of the v3 AVX2 default.
#
# BF16 + AMX 16x16 tile GEMM are NOT gated by this flag — they ride q2-ndarray's
# CPU-AGNOSTIC runtime autodetect polyfill (`simd_caps()` + the AMX `arch_prctl`
# XTILEDATA enable + CPU-model detect). The polyfill opportunistically lights them
# up only when the *runtime* host actually has them, and always keeps the AVX2 /
# scalar paths it compiled in as fallback. So: AVX-512 = compile baseline here;
# BF16/AMX = runtime-detected; everything below v4 = polyfill fallback.
#
# ⚠ REQUIREMENT: a v4 floor makes the binary REQUIRE AVX-512 at run time — it
# SIGILLs on the first `__m512` op on a host without it (the PR #170 failure mode,
# one level up). The Railway *build* machine needs no AVX-512 (compiling != run),
# but the *deploy* host does. AMX additionally needs a Sapphire/Emerald/Granite
# Rapids Xeon at run time; on anything older the autodetect simply skips AMX (that
# is the agnostic polyfill working as intended, not an error). If a deploy target
# may lack AVX-512, drop this to `x86-64-v3` and rely on runtime dispatch for the
# AVX-512/AMX paths — one portable binary, same hot paths when the silicon allows.
ENV CARGO_BUILD_RUSTFLAGS="-C target-cpu=x86-64-v4"
# Build the q2 binary with embedded frontend
WORKDIR /build/q2
RUN cargo build --release -p cockpit-server --features embed-cockpit,planner \
&& ls -lh target/release/q2-cockpit
# ── Runtime ───────────────────────────────────────────────────────────
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates libssl3 curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /build/q2/target/release/q2-cockpit ./q2-cockpit
# Aiwar data for lance-graph hydration at startup
COPY --from=builder /build/q2/cockpit/public/aiwar_graph.json ./data/aiwar_graph.json
COPY --from=builder /build/q2/cockpit/public/aiwar_weapons.json ./data/aiwar_weapons.json
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/health || exit 1
ENV PORT=8080
ENV AIWAR_DATA_PATH=/app/data/aiwar_graph.json
EXPOSE 8080
CMD ["./q2-cockpit"]