git-ents.gitmain
⌘K
foforge
Dockerfile69 lines · 3.7 KB · dockerfilehistorycomment on this file
1# syntax=docker/dockerfile:1
2# The single-node hosted root (`roots.single-node-hosted`,
3# docs/development-plan.adoc phase 6): the `git-ents` binary itself, wired
4# so stock git's own smart-HTTP transport (`git http-backend`, via
5# nginx+fcgiwrap) invokes its `pre-receive`/`post-receive` hooks. No
6# Postgres/Tigris/gix-receive here — that is `git-ents-server`, phase 8.
7#
8# The binary builds *in* this image, from the same source tree the rest
9# of the deploy comes from — never a separately cross-compiled artifact
10# copied in by hand. That used to be `docker/bin/git-ents`, a musl binary
11# built on the host and materialized here before `docker build`; the
12# whole point of that indirection was to skip a slow in-container Rust
13# build, but it silently deployed stale code whenever someone forgot the
14# manual rebuild step, exactly the failure mode a deploy pipeline exists
15# to prevent.
16FROM rust:1-slim-bookworm AS builder
17# musl-tools: the static link target below. git + zig: `libghostty-vt-sys`
18# (behind acdc-converters-html's `terminal` feature) clones ghostty at a
19# pinned commit and builds it with zig from its build script — the same
20# toolchain CI installs via mlugg/setup-zig, pinned to the same 0.15.2.
21RUN apt-get update \
22 && apt-get install -y --no-install-recommends \
23 musl-tools git ca-certificates curl xz-utils \
24 && rm -rf /var/lib/apt/lists/*
25ARG ZIG_VERSION=0.15.2
26RUN curl -fsSL "https://ziglang.org/download/${ZIG_VERSION}/zig-$(uname -m)-linux-${ZIG_VERSION}.tar.xz" \
27 | tar -xJ -C /usr/local \
28 && ln -s "/usr/local/zig-$(uname -m)-linux-${ZIG_VERSION}/zig" /usr/local/bin/zig
29RUN rustup target add x86_64-unknown-linux-musl
30WORKDIR /src
31COPY Cargo.toml Cargo.lock ./
32COPY crates crates
33# Cache mounts, not layer caching: the downloaded-crate registry and
34# cargo's own incremental `target/` survive across separate `flyctl
35# deploy` runs from this machine (Depot's builder persists cache-mount
36# contents independently of the image layers, which invalidate on every
37# source change). Without this, a one-line edit anywhere under `crates/`
38# would recompile the entire dependency graph from scratch every deploy.
39# `sharing=locked` on `target/`: cargo already serializes writes to it
40# with its own lock file, but a locked mount avoids relying on that
41# alone if two builds ever did overlap on the same cache.
42RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \
43 --mount=type=cache,target=/src/target,sharing=locked \
44 cargo build --release --locked --target x86_64-unknown-linux-musl -p git-ents \
45 && cp target/x86_64-unknown-linux-musl/release/git-ents /tmp/git-ents
46
47FROM debian:bookworm-slim AS runtime
48WORKDIR /app
49# git: the bare repo + git-http-backend CGI itself.
50# nginx+fcgiwrap+spawn-fcgi: the smart-HTTP transport (Phase 0's bootstrap,
51# still the transport Phase 6 rides per docs/development-plan.adoc).
52# curl: installs the sprite CLI the post-receive hook shells out to.
53RUN apt-get update \
54 && apt-get install -y --no-install-recommends \
55 git ca-certificates curl nginx fcgiwrap spawn-fcgi \
56 && rm -rf /var/lib/apt/lists/*
57# The sprite CLI runs post-receive's checks in a Sprite; it reads
58# SPRITES_TOKEN from the env. The installer drops the binary in
59# $HOME/.local/bin and never touches PATH, so point it at /usr/local/bin
60# (already on PATH) where the hosted root can spawn it.
61RUN curl -fsSL https://sprites.dev/install.sh \
62 | env SPRITE_INSTALL_PREFERRED_DIRS=/usr/local/bin \
63 SPRITE_INSTALL_DEFAULT_BIN_DIR=/usr/local/bin bash
64COPY --from=builder /tmp/git-ents /usr/local/bin/git-ents
65RUN chmod +x /usr/local/bin/git-ents
66COPY docker/nginx.conf /etc/git-ents/nginx.conf
67COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
68RUN chmod +x /usr/local/bin/entrypoint.sh
69ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]