Context
Permanu's own backend (Dockerfile.production in permanu/Deploy) cannot currently be expressed via Docksmith. Per Permanu's hard dogfood rule (Permanu deploys customer apps via Docksmith, so it must use Docksmith for itself), we need to delete the hand-written Dockerfile — but Docksmith today produces only a single-binary, single-stage Go image. The Permanu BE image needs:
- Custom build target —
go build ./cmd/server (not auto-detected entrypoint), with version ldflags injected via -X (already partially expressible via [build].command, but no first-class "ldflags" field).
- Pinned external binary fetch —
atlas migration tool (https://release.ariga.io/atlas/...) baked into the image at /app/bin/atlas. Server execs literal path; cannot rely on PATH.
- Cross-arch sibling binary —
cmd/permanu-agent cross-built for linux/amd64 + linux/arm64, copied into /app/bin/permanu-agent-linux-{amd64,arm64}. Served via HTTP for agent installs/auto-update.
- Asset copies —
atlas.hcl, sql/, migrations/, templates/ directories must land in image with --chown.
- Entrypoint script —
entrypoint.sh runs atlas migrate apply (gated on env), then execs /app/main. ENTRYPOINT must point at the script, not the binary.
- Alpine runtime override — distroless is wrong here (entrypoint.sh + atlas need a shell + libc + ca-certs + tzdata).
[runtime_config].image = \"alpine:3.21\" may cover it but distroless-by-default for Go means the user fights the tool.
- Custom HEALTHCHECK —
CMD [\"/app/main\", \"health\"] (the binary has a subcommand).
- Custom ENV block —
DEPLOY_ENV=prod, SERVER_PORT=4290, ATLAS_CONFIG=atlas.hcl, ATLAS_ENV=prod.
Why this matters
- Without (1)–(8), Docksmith can't replace
Dockerfile.production. Either Permanu keeps a hand-written Dockerfile (dogfood violation), or Docksmith grows enough to express composite Go images.
- This isn't unique to Permanu. Any Go service that ships sibling binaries (CLI + daemon, multi-arch agents) or bundles a migration tool hits the same wall.
Suggested shape
A [stages] array in docksmith.toml that lets users add stages between detected builder and runtime, plus first-class fields for:
[build].ldflags = [\"-X foo=bar\"]
[[runtime.copy]] blocks (src, dst, chown, from-stage)
[runtime.entrypoint] (script path) + [runtime.cmd]
[runtime.healthcheck] (custom CMD)
[runtime.env] (already exists as [env])
Or alternatively: emit a base Dockerfile and let users append a Dockerfile.overlay that Docksmith concatenates — keeps the simple case simple, lets composite cases extend without forking.
Blocker
Permanu PR #957 (publish BE image to ghcr.io) and PR #958 (one-shot install.sh) both need to drop Dockerfile.production to comply with the dogfood rule. They are blocked on this gap. Permanu cannot delete Dockerfile.production until Docksmith can produce an equivalent — every gap above maps to a real runtime requirement (atlas migration gate, agent binary serving, template loading).
Context
Permanu's own backend (
Dockerfile.productioninpermanu/Deploy) cannot currently be expressed via Docksmith. Per Permanu's hard dogfood rule (Permanu deploys customer apps via Docksmith, so it must use Docksmith for itself), we need to delete the hand-written Dockerfile — but Docksmith today produces only a single-binary, single-stage Go image. The Permanu BE image needs:go build ./cmd/server(not auto-detected entrypoint), with version ldflags injected via-X(already partially expressible via[build].command, but no first-class "ldflags" field).atlasmigration tool (https://release.ariga.io/atlas/...) baked into the image at/app/bin/atlas. Server execs literal path; cannot rely on PATH.cmd/permanu-agentcross-built forlinux/amd64+linux/arm64, copied into/app/bin/permanu-agent-linux-{amd64,arm64}. Served via HTTP for agent installs/auto-update.atlas.hcl,sql/,migrations/,templates/directories must land in image with--chown.entrypoint.shrunsatlas migrate apply(gated on env), then execs/app/main. ENTRYPOINT must point at the script, not the binary.[runtime_config].image = \"alpine:3.21\"may cover it but distroless-by-default for Go means the user fights the tool.CMD [\"/app/main\", \"health\"](the binary has a subcommand).DEPLOY_ENV=prod,SERVER_PORT=4290,ATLAS_CONFIG=atlas.hcl,ATLAS_ENV=prod.Why this matters
Dockerfile.production. Either Permanu keeps a hand-written Dockerfile (dogfood violation), or Docksmith grows enough to express composite Go images.Suggested shape
A
[stages]array indocksmith.tomlthat lets users add stages between detectedbuilderandruntime, plus first-class fields for:[build].ldflags = [\"-X foo=bar\"][[runtime.copy]]blocks (src, dst, chown, from-stage)[runtime.entrypoint](script path) +[runtime.cmd][runtime.healthcheck](custom CMD)[runtime.env](already exists as[env])Or alternatively: emit a base Dockerfile and let users append a
Dockerfile.overlaythat Docksmith concatenates — keeps the simple case simple, lets composite cases extend without forking.Blocker
Permanu PR #957 (publish BE image to ghcr.io) and PR #958 (one-shot install.sh) both need to drop
Dockerfile.productionto comply with the dogfood rule. They are blocked on this gap. Permanu cannot deleteDockerfile.productionuntil Docksmith can produce an equivalent — every gap above maps to a real runtime requirement (atlas migration gate, agent binary serving, template loading).