aboutsummaryrefslogtreecommitdiff
path: root/Containerfile
diff options
context:
space:
mode:
Diffstat (limited to 'Containerfile')
-rw-r--r--Containerfile30
1 files changed, 30 insertions, 0 deletions
diff --git a/Containerfile b/Containerfile
new file mode 100644
index 0000000..1cb79e7
--- /dev/null
+++ b/Containerfile
@@ -0,0 +1,30 @@
+# git-forge: one binary, one data directory, one listener. Strictly Alpine,
+# both stages, so there is one distribution to reason about.
+
+FROM alpine:3.23 AS build
+RUN apk add --no-cache go
+WORKDIR /src
+COPY go.mod go.sum ./
+RUN go mod download
+COPY . .
+# Static, so the runtime image needs neither Go nor libc.
+RUN CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o /git-forge .
+
+FROM alpine:3.23
+# git-daemon is not the daemon here: in Alpine that subpackage is where
+# git-http-backend lives, and without it every clone and push answers 500.
+# tini reaps what git leaves: a detached gc is reparented to PID 1 and would
+# otherwise stay a zombie.
+RUN apk add --no-cache git git-daemon cgit highlight ca-certificates tini
+COPY --from=build /git-forge /usr/local/bin/git-forge
+
+# Non-root, and the datadir is credential material, so 0700 and one owner.
+RUN adduser -D -H -u 1000 forge \
+ && install -d -o forge -g forge -m 0700 /var/lib/git-forge
+USER forge
+ENV HOME=/tmp
+
+EXPOSE 8080
+VOLUME /var/lib/git-forge
+HEALTHCHECK --interval=30s --timeout=5s CMD wget -qO- http://127.0.0.1:8080/healthz || exit 1
+ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/git-forge"]