mirror of
https://github.com/therealaleph/MasterHttpRelayVPN-RUST.git
synced 2026-05-17 21:24:48 +03:00
08efbc571d
The tunnel-docker job in v1.7.3 release failed with:
error: failed to unpack package `serde_json v1.0.149`
Caused by: failed to open `/usr/local/cargo/registry/src/.../serde_json-1.0.149/.cargo-ok`
Caused by: File exists (os error 17)
Root cause: BuildKit's default cache-mount sharing is "shared" — both
linux/amd64 and linux/arm64 build stages mount the SAME on-disk cache
dir. Cargo's registry source extraction is non-atomic; both arches
race on `tar -xzf serde_json-1.0.149.crate` into the same destination,
and the loser hits EEXIST mid-unpack.
Fix: scope each cache mount with `id=cargo-registry-${TARGETPLATFORM}`
(and matching for cargo-git + target). BuildKit then keeps separate
on-disk caches per architecture — no race. Per-arch warm-build speedup
is preserved (each cache fills with that arch's pre-built deps); the
only loss is one cache miss per arch on the first build after this
change, which we already paid in v1.7.3.
The target/ mount is also platform-scoped since target/ holds compiled
object files for a single ABI; sharing across arches would either miss
or, worse, link wrong-ABI objects together.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
75 lines
3.4 KiB
Docker
75 lines
3.4 KiB
Docker
# syntax=docker/dockerfile:1
|
|
#
|
|
# Multi-stage build for the mhrv-tunnel-node service.
|
|
#
|
|
# Build stage compiles a release binary against rust 1.85 (matches MSRV in
|
|
# Cargo.toml). Cargo's incremental build cache is mounted via BuildKit
|
|
# `--mount=type=cache` so a `docker build` against an unchanged dependency
|
|
# tree skips re-downloading + re-compiling crates — first build ~6 min,
|
|
# warm builds ~30 s.
|
|
#
|
|
# Runtime stage is `debian:bookworm-slim` for libc compatibility (the
|
|
# binary dynamically links against glibc) plus `ca-certificates` so HTTPS
|
|
# upstream URLs from `data` ops can do TLS handshake. Image stays under
|
|
# 100 MB end-to-end.
|
|
#
|
|
# Runs as a dedicated non-root `tunnel` user (uid 1000) — the service
|
|
# never needs to write outside its own process state, so no reason to
|
|
# give it root.
|
|
#
|
|
# Required env vars:
|
|
# TUNNEL_AUTH_KEY shared secret matching `const TUNNEL_AUTH_KEY` in
|
|
# CodeFull.gs. The service refuses every request
|
|
# without a matching key.
|
|
# PORT HTTP listen port. Defaults to 8080 if unset.
|
|
#
|
|
# Health: the service responds to `GET /` with a small status JSON. Add
|
|
# `--health-cmd 'curl -fsS http://localhost:8080/ || exit 1'` on the
|
|
# `docker run` if you want compose-level health gating.
|
|
|
|
FROM rust:1.85-slim AS builder
|
|
WORKDIR /app
|
|
# Copy lockfile so cargo uses pinned versions identically to local builds.
|
|
COPY Cargo.toml Cargo.lock ./
|
|
COPY src/ ./src/
|
|
# BuildKit cache mounts: cargo's registry/git caches and the target/
|
|
# directory persist across builds, dramatically speeding up rebuilds when
|
|
# only application code changes.
|
|
#
|
|
# `id=...-$TARGETPLATFORM` is load-bearing on multi-arch builds. Without
|
|
# it, BuildKit defaults to a single shared cache across architectures
|
|
# and the `linux/amd64` + `linux/arm64` jobs race on the same on-disk
|
|
# `/usr/local/cargo/registry/src/.../<crate>/.cargo-ok` extraction. The
|
|
# second-arriving arch hits `File exists (os error 17)` mid-unpack and
|
|
# the whole multi-arch build fails. Per-platform cache id keeps each
|
|
# arch's cache isolated; warm-build speedup is preserved per-arch.
|
|
# `target` cache is also platform-scoped because target/ holds object
|
|
# files for one ABI and sharing them across arches would just produce
|
|
# misses or, worse, invalid linking.
|
|
ARG TARGETPLATFORM
|
|
RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry-${TARGETPLATFORM} \
|
|
--mount=type=cache,target=/usr/local/cargo/git,id=cargo-git-${TARGETPLATFORM} \
|
|
--mount=type=cache,target=/app/target,id=app-target-${TARGETPLATFORM} \
|
|
cargo build --release --bin tunnel-node && \
|
|
cp /app/target/release/tunnel-node /usr/local/bin/tunnel-node
|
|
|
|
FROM debian:bookworm-slim
|
|
# `ca-certificates` for HTTPS upstream targets; nothing else needed at
|
|
# runtime since the binary is statically linked against musl-equivalents
|
|
# only for the parts that don't touch glibc.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends ca-certificates \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Non-root runtime user. The service does no filesystem writes outside
|
|
# /tmp, so a static-uid unprivileged user is sufficient and prevents
|
|
# accidental host-FS writes if the container is volume-mounted.
|
|
RUN useradd --system --uid 1000 --no-create-home --shell /usr/sbin/nologin tunnel
|
|
|
|
COPY --from=builder /usr/local/bin/tunnel-node /usr/local/bin/tunnel-node
|
|
|
|
USER tunnel
|
|
ENV PORT=8080
|
|
EXPOSE 8080
|
|
ENTRYPOINT ["tunnel-node"]
|