# syntax=docker/dockerfile:1 # knotless-serve and the web pages it hands on to, in one image, with # knotless-run, knotless-triage, knotless-agent, knotless-mcp and the knotless CLI: the # compose file in deploy/ runs it once as each of serve, the pages and, if # asked, the runner, the triager and the reviewer. # # docker build -t knotless:current . FROM rust:1-bookworm AS serve WORKDIR /src COPY . . # The cache mounts keep the registry and the build between builds on the # same machine, so a change rebuilds the crates it touches and not the rest. # The deploy profile (Cargo.toml) is release's, built for the build's time. RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/src/target \ cargo build --profile deploy --locked \ -p knotless-serve --bin knotless-serve \ -p knotless-run --bin knotless-run \ -p knotless-triage --bin knotless-triage \ -p knotless-agent --bin knotless-agent \ -p knotless-mcp --bin knotless-mcp \ -p knotless --bin knotless \ && cp target/deploy/knotless-serve target/deploy/knotless-run target/deploy/knotless-triage \ target/deploy/knotless-agent target/deploy/knotless-mcp target/deploy/knotless / # Zoekt, which knotless-serve runs for code search: its indexer and its # webserver, at the commit the test check builds them from. FROM golang:1.27.3-bookworm AS zoekt ARG ZOEKT_COMMIT=e1fafb15177040d792bd7c8c41a24a0fb39aada4 RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ CGO_ENABLED=0 GOBIN=/out go install \ github.com/sourcegraph/zoekt/cmd/zoekt-git-index@$ZOEKT_COMMIT \ github.com/sourcegraph/zoekt/cmd/zoekt-webserver@$ZOEKT_COMMIT # The docs, as a Starlight site the pages serve at /docs: docs-site/ reads # docs/, the lexicons and the pages' tokens from beside it. FROM node:24-bookworm-slim AS docs WORKDIR /site/docs-site COPY docs-site/package.json docs-site/package-lock.json ./ RUN npm ci --no-audit --no-fund COPY docs-site/ ./ COPY docs/ /site/docs/ COPY lexicons/ /site/lexicons/ COPY web/src/tokens.css /site/web/src/tokens.css RUN npm run build FROM node:24-bookworm-slim AS pages WORKDIR /web COPY web/package.json web/package-lock.json ./ RUN npm ci --no-audit --no-fund COPY web/ ./ COPY lexicons/ /lexicons/ # Into static/ before the build: adapter-node serves only the files it # found there as it built. COPY --from=docs /site/docs-site/dist static/docs/ RUN npm run build # adapter-node bundles what the pages import, so the build needs no # node_modules beside it. FROM node:24-bookworm-slim RUN apt-get update \ && apt-get install -y --no-install-recommends git ca-certificates tini \ && rm -rf /var/lib/apt/lists/* # Claude Code, which knotless-claude-review has review pulls for # knotless-agent, reading them through knotless-mcp. RUN npm install -g --no-audit --no-fund @anthropic-ai/claude-code@2.1.314 \ && npm cache clean --force COPY --from=serve /knotless-serve /knotless-run /knotless-triage /knotless-agent /knotless-mcp \ /knotless /usr/local/bin/ COPY --from=zoekt /out/zoekt-git-index /out/zoekt-webserver /usr/local/bin/ COPY crates/knotless-agent/claude-review /usr/local/bin/knotless-claude-review # The docker client, for knotless-run's steps: they run on the host's # daemon, through its socket. COPY --from=docker:28-cli /usr/local/bin/docker /usr/local/bin/docker COPY --from=pages /web/build /app/build COPY --from=pages /web/package.json /app/package.json # What knotless-run is, for a deploy to leave a runner running whose is the # same (deploy/deploy.sh): its binary, the docker client its steps run # through, and the packages installed, git and the libraries among them. RUN sha256sum /usr/local/bin/knotless-run /usr/local/bin/docker /var/lib/dpkg/status \ | sha256sum | cut -d ' ' -f 1 > /etc/knotless-run.fingerprint USER node # The commit, from deploy.sh, that the binaries log they run. Set as they # run rather than built in, and last, it changes no binary and no layer # before it: a runner built at another commit from the same code is the # same runner. ARG KNOTLESS_COMMIT ENV KNOTLESS_COMMIT=$KNOTLESS_COMMIT ENTRYPOINT ["tini", "--"] CMD ["knotless-serve", "--listen", "0.0.0.0:2590"]