Skip to content

feat(docker): give the image the tools template hooks actually call - #148

Merged
Ilyes512 merged 4 commits into
mainfrom
feat/docker-image-hook-toolchain
Sep 18, 2026
Merged

Ilyes512 merged 4 commits into
mainfrom
feat/docker-image-hook-toolchain

Conversation

@Ilyes512

Copy link
Copy Markdown
Member

Summary

  • Add git, task, and the docker CLI + compose plugin to the debian runtime stage, pinned to the versions the vhs and bats stages already use.
  • Set init.defaultBranch main so a git init hook does not hand back master where a host produces main.
  • Document the sibling-container contract in the Docker installation docs: the socket needs --group-add 0, and the work directory must be mounted at its own path rather than /work.
  • Four new cases in test/image.bats covering the toolchain, the compose plugin, and git under a foreign uid.

Why

The runtime stage shipped bash and nothing else, so a hook got as far as command not found with the tree already written. Running specsnl/specs-laravel-project through the image failed on its first hook (task: command not found), leaving a scaffold with no .env and no git repo while specs use exited non-zero.

With this, that template completes all four of its post-use hooks in the container, and the result matches the host scaffold apart from one APP_URL line the template's own hook rewrites only on darwin.

Mounting at /work is not enough for hooks that start containers: the daemon resolves a sibling's bind mounts against the host, so the hook asks for a path the host does not have and fails against a tree that looks fine from inside.

The runtime stage shipped bash and nothing else, so a hook got exactly as far
as `command not found` — with the tree already written. Running
specsnl/specs-laravel-project through the image failed on its first hook
(`task: command not found`) and left a scaffold with no .env and no git repo,
while `specs use` exited non-zero.

Adds git, task, and the docker CLI with the compose plugin, pinned to the same
versions the vhs and bats stages already use. git also gets
init.defaultBranch=main so a `git init` hook does not hand back `master` where a
host would produce `main`.

With these, that template now completes all four of its post-use hooks in the
container, and the result is identical to the host scaffold apart from one
APP_URL line the template's own hook rewrites only on darwin.

Documents the sibling-container contract this exposes: a hook running docker
needs the socket (--group-add 0 past its root:root 0660) and the work directory
mounted at its own path, because the daemon resolves a sibling's bind mounts
against the host — at /work the hook asks for a path the host does not have.
The install list and the bats case name already say which tools the image
carries and why a hook needs them.
TASK_VERSION, DOCKER_VERSION and COMPOSE_VERSION were repeated across the
vhs, bats and debian stages, so a bump meant editing the same number in up to
three places. They move to a global ARG block above the first FROM; the stages
re-declare the bare names to pull them into scope.

The downloads are all `curl | tar`, where the default /bin/sh reports only
tar's exit status — a failed download only surfaces because tar happens to
choke on the truncated stream. SHELL with -o pipefail puts that back on the
shell: bash for the Debian-based stages, busybox ash for the Alpine one.

The base stage also drops the apt lists like the other stages already did.
`task lint:docker` runs hadolint through a compose service under the lint
profile, the same shape as golangci-lint. CI runs the task itself rather than
hadolint/hadolint-action, which ships its own hadolint build and would put the
version in a second place to keep in sync.

Version pinning is off in .hadolint.yml: pinning every apt/apk package on top
of an already pinned base image trades a reproducible build for one that breaks
the moment the distro moves a package version.
@Ilyes512
Ilyes512 merged commit b6c3993 into main Sep 18, 2026
8 checks passed
@Ilyes512
Ilyes512 deleted the feat/docker-image-hook-toolchain branch September 18, 2026 10:32
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