Skip to content

build: armv7 image, release binaries, gosec, exec-form entrypoint - #94

Merged
marvinvr merged 2 commits into
issue-81from
issue-103
Sep 30, 2026
Merged

marvinvr merged 2 commits into
issue-81from
issue-103

Conversation

@marvinvr

Copy link
Copy Markdown
Owner

Stacked on #93. Merge that one first. Until it merges, this diff also shows #93's commit. This PR's own commits are the last two.

What changes

armv7 image. The image now also builds for linux/arm/v7 (Raspberry Pi 2/3, older 32-bit ARM NAS boxes), next to amd64 and arm64. The base images (golang:1.25-alpine, alpine, tailscale/tailscale) all publish arm/v7. The builder stage now runs on $BUILDPLATFORM and cross-compiles (CGO is off). QEMU only runs the runtime stage's apk add, not the Go toolchain. The CI docker matrix gained the same leg. Each arch in the release workflow now gets its own GHA cache scope, so the three legs no longer overwrite each other's cache.

Release binaries. .goreleaser.yaml builds static Linux binaries for amd64, arm64 and armv7, plus checksums.txt. They carry the same -X github.com/marvinvr/docktail/version.Version=<tag> stamp as the image. The new release.yaml runs when a GitHub release is published, or by hand with a tag. It runs GoReleaser with --skip=publish and uploads the archives with gh release upload, so the release's hand-written name and notes stay untouched. It deliberately does not run on every tag push: tags are cut much more often than releases, and running on each one would create a release per tag. A new release-snapshot CI job builds the archives on every PR, so a broken config fails here rather than on release day.

gosec. Enabled through golangci-lint. Two kinds of finding were real fixes:

  • uint64 byte counts from the Docker stats API and from statfs now saturate instead of wrapping negative.

Every other finding has a //nolint:gosec with the reason:

  • reconnect jitter (math/rand)
  • operator-configured file paths
  • the fixed tailscale binary exec'd with argv only
  • a public OAuth token URL
  • sysfs reads
  • the docs generator's output permissions and template

ENTRYPOINT ["/app/docktail"]. The sh -c "sleep 1 && exec …" wrapper is gone. The sleep did have a job: with a sidecar behind a plain depends_on, tailscaled may not be listening yet, and the first reconcile then fails and waits a full RECONCILE_INTERVAL. The socket watchdog does not cover that case; it only avoids exiting before the socket was ever seen. DockTail now waits for the socket itself, up to 15s, before the version check and the first reconcile. It returns as soon as the socket is reachable, logs a warning if it never becomes reachable, and exits cleanly on SIGTERM during the wait.

Runtime packages. iptables/ip6tables are dropped. They came in with the old apk add tailscale install. The image now only copies the tailscale CLI and runs no daemon, and nothing in DockTail uses them.

Docs. docs/02-installation.md gets a new Platforms And Release Binaries section: the image platforms, the binaries, and what the binary needs outside a container. The same page covers the tailscale CLI on PATH, socket access, and a restart supervisor. Also updated: the startup-wait note in docs/07-reference.md, the simpler docker run … --version there, and a one-line pointer in the README.

Release-notes worthy

  • Arguments passed to the container (a compose command: or extra docker run args) used to be dropped silently by the shell wrapper. They now reach docktail, which rejects unknown arguments. docker run ghcr.io/marvinvr/docktail --version now works directly.
  • Binaries only attach to releases published after this merges. Patch tags without a GitHub release get images only.

Refs marvinvr/docktail-cloud#103

- Publish the image for linux/arm/v7 alongside amd64 and arm64. The Go
  binary is cross-compiled on the build platform, so only the runtime
  stage runs under QEMU.
- Build static Linux binaries (amd64, arm64, armv7) with GoReleaser and
  attach them, with checksums, to each published GitHub release. CI builds
  a snapshot so a broken config fails on the PR.
- Enable gosec in golangci-lint. Byte counts from Docker and statfs now
  saturate instead of wrapping; the remaining findings are annotated with
  why they are safe.
- ENTRYPOINT is now ["/app/docktail"]. The shell's `sleep 1` gave a
  starting tailscaled a head start; DockTail now waits for the socket
  itself (up to 15s) before the version check and the first reconcile.
- Drop iptables/ip6tables from the runtime image. They came in with the
  Alpine tailscale package; the image only carries the tailscale CLI and
  runs no daemon.
@marvinvr
marvinvr changed the base branch from main to issue-81 September 24, 2026 04:12
@marvinvr
marvinvr added this pull request to stack #99 September 24, 2026 04:12
@marvinvr
marvinvr merged commit d8e6f3b into main Sep 30, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant