mirror of
https://github.com/Twigpine/node.git
synced 2026-11-08 17:55:53 -10:00
The Dockerfile cache layer primed from four crate manifests while the workspace has six members, and crates/gl takes a path dependency on icaptcha-client. Cargo loads the whole workspace before resolving, so the layer aborted on the missing manifest and || true swallowed it. Every image build has been a full cold build since icaptcha-client landed, including the docker-build smoke test on every PR. Copy all six manifests, and drop the || true: the layer is expected to succeed, and tolerating its failure is what let this sit dead unnoticed. Dockerfile.bins pinned rust:1.85-bookworm against a workspace rust-version of 1.91. An unmet MSRV is a hard cargo error, so both Linux musl targets of scripts/build-bins.sh have been unbuildable. Nothing in CI builds that file, which is why nothing reported it. Closes #265 Closes #266
97 lines
4.5 KiB
Docker
97 lines
4.5 KiB
Docker
# syntax=docker/dockerfile:1.6
|
|
#
|
|
# gitlawb-node — production image for operators.
|
|
# Multi-arch (linux/amd64, linux/arm64), non-root runtime, HEALTHCHECK.
|
|
|
|
# ── Build stage ─────────────────────────────────────────────────────────────
|
|
FROM rust:1.91-bookworm AS builder
|
|
|
|
WORKDIR /build
|
|
|
|
# Cache dependencies first for faster rebuilds.
|
|
# EVERY workspace member's manifest must be copied here, not just the ones this
|
|
# image ships: cargo loads the whole workspace before it resolves anything, so a
|
|
# missing member's Cargo.toml (or a path dependency pointing at one) aborts the
|
|
# layer before a single crate is fetched.
|
|
COPY Cargo.toml Cargo.lock ./
|
|
COPY crates/gitlawb-core/Cargo.toml crates/gitlawb-core/
|
|
COPY crates/gitlawb-node/Cargo.toml crates/gitlawb-node/
|
|
COPY crates/gl/Cargo.toml crates/gl/
|
|
COPY crates/git-remote-gitlawb/Cargo.toml crates/git-remote-gitlawb/
|
|
COPY crates/gitlawb-attest/Cargo.toml crates/gitlawb-attest/
|
|
COPY crates/icaptcha-client/Cargo.toml crates/icaptcha-client/
|
|
|
|
# Fetch deps (this layer caches until Cargo.{toml,lock} change).
|
|
# No `|| true`: this layer is expected to succeed, and swallowing its exit code
|
|
# is what let it sit dead from the moment gl gained a path dependency on
|
|
# icaptcha-client. A failure here should stop the build, not silently turn every
|
|
# image build into a cold one.
|
|
RUN mkdir -p crates/gitlawb-core/src crates/gitlawb-node/src crates/gl/src \
|
|
crates/git-remote-gitlawb/src crates/gitlawb-attest/src crates/icaptcha-client/src && \
|
|
echo 'fn main() {}' > crates/gitlawb-node/src/main.rs && \
|
|
echo 'fn main() {}' > crates/gl/src/main.rs && \
|
|
echo 'fn main() {}' > crates/git-remote-gitlawb/src/main.rs && \
|
|
echo '' > crates/gitlawb-core/src/lib.rs && \
|
|
echo '' > crates/gitlawb-attest/src/lib.rs && \
|
|
echo '' > crates/icaptcha-client/src/lib.rs && \
|
|
cargo build --release --locked -p gitlawb-node -p gl -p git-remote-gitlawb
|
|
|
|
# Now copy real sources and build for real.
|
|
# Force-bump mtimes so cargo's fingerprint check rebuilds — without this,
|
|
# cargo can keep the dummy `fn main() {}` binaries from the cache layer above
|
|
# and the runtime container exits immediately with code 0.
|
|
COPY crates/ crates/
|
|
COPY bootstrap-peers.json ./
|
|
RUN find crates -name "*.rs" -exec touch {} + && \
|
|
rm -f target/release/gitlawb-node target/release/gl target/release/git-remote-gitlawb && \
|
|
rm -rf target/release/.fingerprint/gitlawb-node-* \
|
|
target/release/.fingerprint/gl-* \
|
|
target/release/.fingerprint/git-remote-gitlawb-* && \
|
|
cargo build --release --locked -p gitlawb-node -p gl -p git-remote-gitlawb && \
|
|
strip target/release/gitlawb-node target/release/gl target/release/git-remote-gitlawb
|
|
|
|
# ── Runtime stage ───────────────────────────────────────────────────────────
|
|
FROM debian:bookworm-slim
|
|
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
git \
|
|
ca-certificates \
|
|
curl \
|
|
tini \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Non-root user for runtime
|
|
RUN groupadd -r gitlawb --gid=1000 \
|
|
&& useradd -r -g gitlawb --uid=1000 --home-dir=/data --shell=/sbin/nologin gitlawb \
|
|
&& mkdir -p /data/repos /data/keys \
|
|
&& chown -R gitlawb:gitlawb /data
|
|
|
|
COPY --from=builder /build/target/release/gitlawb-node /usr/local/bin/
|
|
COPY --from=builder /build/target/release/gl /usr/local/bin/
|
|
COPY --from=builder /build/target/release/git-remote-gitlawb /usr/local/bin/
|
|
|
|
USER gitlawb
|
|
WORKDIR /data
|
|
|
|
ENV GITLAWB_REPOS_DIR=/data/repos \
|
|
GITLAWB_KEY=/data/keys/identity.pem \
|
|
GITLAWB_HOST=0.0.0.0 \
|
|
GITLAWB_PORT=7545 \
|
|
GITLAWB_P2P_PORT=7546
|
|
|
|
EXPOSE 7545 7546/udp
|
|
|
|
VOLUME ["/data"]
|
|
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
|
CMD curl -fsS http://127.0.0.1:${GITLAWB_PORT}/health || exit 1
|
|
|
|
# Run under tini so the node is never PID 1. As PID 1 a process must reap
|
|
# reparented orphans itself; the node does not, so git's reparented grandchildren
|
|
# (e.g. pack-objects orphaned when a served upload-pack dies on a client
|
|
# disconnect) would accumulate as zombies until fork() fails with EAGAIN (#53).
|
|
# tini reaps them and forwards SIGTERM/SIGINT to the node, which runs its own
|
|
# graceful shutdown. (No `-g`: the node manages its own children, so group-wide
|
|
# signalling would only disturb in-flight git helpers during shutdown.)
|
|
ENTRYPOINT ["tini", "--", "gitlawb-node"]
|