chore(docker): bump alpine 3.21 to 3.24 in the backup-tools and runtime stages (agent-os-bmo) - #51
Merged
Merged
Conversation
…tages (agent-os-bmo) Patch-grade hygiene bump on a trusted base: agent-os-o9l's Trivy baseline found zero findings from alpine 3.21.7 itself, so there is no security pressure behind this change. Three releases in one step still changes the package set underneath restic, rclone, the docker CLI plugins, and the entrypoint's su-exec/shadow usage, so it is validated with a full backup/restore drill against the rebuilt image rather than a CI glance alone. Drill (API-driven, AUTH_DISABLED=true, docker.sock mounted, --network host): repo init -> backup run (WS-triggered) -> snapshot listed with capstan tags -> preview lists expected paths -> stack dir destroyed and seeded with a wrong placeholder file -> restore run (WS-triggered) -> sha256 over the 3 original files identical pre/post-restore, and the deliberately-wrong data.txt was overwritten with the correct original content, proving restore actually wrote rather than no-oping -> restic check --read-data reports "no errors were found". Also verified: entrypoint.sh's docker.sock GID discovery (dockerhost group created at GID 130, appuser joined), server runs as non-root appuser (uid=1000), and docker/compose/buildx/wget all execute inside the container (docker-cli 27.3.1->29.5.3, buildx 0.19.1->0.34.1, compose 2.31.0->5.1.4 majors; su-exec 0.2->0.3, shadow 4.16.0->4.18.0 patch bumps; restic 0.19.1 and rclone 1.74.4 unchanged since they are pinned static binaries fetched independently of the alpine base). Deliberately excludes the golang:1.25.12-alpine builder image and backend/go.mod. Those two must move together: go.mod pins "toolchain go1.25.12", and with GOTOOLCHAIN=auto a newer builder image just downloads and re-execs into that pinned toolchain on every build, so bumping the Dockerfile's Go image alone adds a network toolchain fetch to every build for no change in the shipped binary, while putting the two pins out of step. Moving to Go 1.26 is a real decision that must change both files together in one reviewed change, and is deferred to a separate PR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Takes the alpine half of Dependabot #13. The Go 1.25.12 → 1.26.5 builder bump is deliberately excluded — see below.
Changes
Two lines in
docker/Dockerfile:alpine:3.21→alpine:3.24at:67(backup-tools stage) and:124(runtime stage). Nothing else.Why alpine is taken but drilled
agent-os-o9l's Trivy baseline established alpine 3.21.7 contributes zero findings — the fixable HIGH/CRITICAL surface was all in restic and rclone, cleared byagent-os-9e1. So there is no security pressure here; it is patch-grade hygiene on a trusted base.But three releases in one step changes the package set underneath restic, rclone, the docker CLI plugins and the entrypoint's
su-exec/shadowusage. What actually moved:restic and rclone are pinned static binaries downloaded independently of the base, so the backup engine itself does not move. All the risk is in the apk-provided tooling — and compose jumped three majors.
Two drills
Backup/restore. Repo init → run → snapshot listed with capstan tags → preview → destroy the stack dir → restore → sha256 byte-for-byte identical pre/post →
restic check --read-datareports "no errors were found". A deliberately-wrongdata.txtwas planted before the restore and came back with the correct original content, proving the restore actually wrote rather than leaving already-correct files alone.Compose lifecycle, because the first drill touches no compose code at all and would have passed identically if every stack operation were broken. Start → status → pull → stop through the API, each cross-checked against
docker psindependently rather than trusting the API's own report.The load-bearing result:
parseComposePSOutput(docker_lifecycle.go:491-533) unmarshalsdocker compose ps --format jsoninto an anonymous struct readingID,Name,Service,State,Health,Image,Ports. All seven are present and correctly cased in compose v5.1.4's output. This matters because that function silentlycontinues on unmarshal error — a changed JSON schema would not fail loudly, it would yield zero containers and report a running stack asstopped. Verified it does not.Also confirmed under the new base: entrypoint socket-GID discovery still builds the
dockerhostgroup (GID 130,appuserjoined), PID 1 still runs as uid 1000,wgetstill serves the healthcheck (docker inspectreportshealthy), anddocker/docker compose/docker buildxall execute in-container.Why the Go bump is excluded
backend/go.modcarries bothgo 1.25.0andtoolchain go1.25.12, andagent-os-vkrestablished that go.mod's toolchain and the Dockerfile's builder must move together. WithGOTOOLCHAIN=auto, a 1.26.5 builder readingtoolchain go1.25.12downloads and re-execs into 1.25.12 anyway — so the bump would add a toolchain download to every image build, over the network, for no change in the shipped binary, while putting the two pins out of step. Moving to Go 1.26 is a real decision that must change both files in one reviewed change, and a Go minor can shift vet/lint behaviour, which would land on top of golangci-lint arriving viaagent-os-far.Switching the runtime base to debian-slim was considered and rejected: the usual musl arguments do not apply (
CGO_ENABLED=0atdocker/Dockerfile:59against pure-Gomodernc.org/sqlite, so no libc is linked), while the costs are concrete — no default-repo docker-cli/buildx/compose, nosu-exec, differingaddgroup/adduserflags, nowget.Closes
agent-os-bmo.🤖 Generated with Claude Code