Conversation
This was referenced Aug 7, 2026
dcasota
force-pushed
the
fix/docker-init-static-5.0
branch
from
August 7, 2026 21:55
8e70895 to
35bfb22
Compare
dcasota
force-pushed
the
fix/docker-init-static-5.0
branch
from
September 1, 2026 10:25
f59dcc7 to
f97ac7d
Compare
`docker run --init` fails on any container whose rootfs has no glibc loader:
exec /sbin/docker-init: no such file or directory
/sbin/docker-init is not a host path. It is the hardcoded in-container
destination (inContainerInitPath in moby daemon/oci_linux.go); the daemon
resolves the host binary via LookupInitPath() and bind-mounts it there, then
execs it as PID 1 inside the container. Because /usr/bin/docker-init is a
dynamic PIE, the kernel must load /lib64/ld-linux-x86-64.so.2 from the
*container's* rootfs. Alpine/musl, scratch and distroless images do not have
it, and execve reports the missing interpreter as ENOENT - which surfaces as
"no such file or directory" for a file that plainly exists.
This regressed in 27.3.1-5 (commit b3da2fa, "tini: Initial commit / Also
seperate out tini from docker spec"). Before it, docker.spec built tini itself
and installed a statically linked binary:
make tini-static
cp tini-static "$GOPATH/bin/docker-init"
after it, docker-init became a symlink to the dynamically linked /usr/bin/tini
from the new standalone tini package, whose spec builds tini-static and then
discards it with %exclude.
Upstream moby links docker-init statically on purpose
(hack/dockerfile/install/tini.installer runs `make tini-static`, and the
Dockerfile asserts it with `xx-verify --static`). Fedora does the same: its
tini package ships a tini-static subpackage that moby-engine depends on.
photon master/dev/4.0 are unaffected, they still build it statically.
Changes:
tini: package tini-static in a new subpackage instead of excluding it. The
binary is already built and installed into the buildroot by %cmake_build /
%cmake_install - the %exclude only existed to stop RPM's unpackaged-files
check from failing the build.
tini: restore tini-disable-git.patch, dropped by b3da2fa. tini's
CMakeLists.txt overwrites tini_VERSION_GIT and git_version_check_ret from
execute_process(), clobbering the -D values the spec passes. An RPM builds
from a tarball with no .git, so the git call fails and the version suffix is
silently dropped. moby parses `docker-init --version` expecting
"tini version X.Y.Z - git.COMMIT", so `docker info` showed an empty
"init version:". With the patch both binaries report
"tini version 0.19.0 - git.de40ad0" again.
docker: 5.0 gates docker by subrelease, so both copies are fixed -
SPECS/docker/docker.spec (photon_subrelease >= 91) and
SPECS/90/docker/docker.spec (photon_subrelease <= 90). SPECS/tini/tini.spec
is not gated, so the tini-static subpackage covers every subrelease.
Both point docker-init at tini-static, and add a versioned
Requires: tini-static >= 0.19.0-3 to docker-engine, which is the subpackage
that actually ships /usr/bin/docker-init. The version is required: an
unversioned dependency could be satisfied by an older tini that has no
tini-static, leaving the symlink dangling and reproducing the identical
error message.
Verified on Photon 5.0 with docker-29.5.3-1.ph5 / tini-0.19.0-2.ph5:
before: docker run --init nginx:1-alpine -> exec /sbin/docker-init: ...
docker run --init debian:12 -> works (glibc image)
after: both work, and `ps` in the container shows PID 1 = docker-init
Change-Id: I0b08ef69c111b299fad06874c7fb1e306a040622
Signed-off-by: Daniel Casota <dcasota@gmail.com>
dcasota
force-pushed
the
fix/docker-init-static-5.0
branch
from
September 14, 2026 09:17
f97ac7d to
38c9bde
Compare
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.
Part of #1605.
docker run --init(and composeinit: true) fails on any container whose rootfs has no glibc loader:/sbin/docker-initis not a host pathIt is the hardcoded in-container destination. From moby
daemon/oci_linux.go:LookupInitPath()searches the libexec dirs and then$PATH, finds/usr/bin/docker-init, and bind-mounts it (the symlink is resolved by the mount) into the container, which then execs it as PID 1.Why it fails
/usr/bin/docker-initis a dynamic PIE, so the kernel must load/lib64/ld-linux-x86-64.so.2from the container's rootfs. Alpine only ships/lib/ld-musl-x86_64.so.1.execvereports a missing ELF interpreter asENOENT, which surfaces as "no such file or directory" for a file that is plainly present.Reproduced on Photon 5.0 with
docker-29.5.3-1.ph5/tini-0.19.0-2.ph5:debian:12succeeding is the control: a wrong host path would break every image, not only those without a glibc loader.Where it regressed
Commit b3da2fa ("tini: Initial commit / Also seperate out tini from docker spec"), released as
docker-27.3.1-5.ph5. Before it,docker.specbuilt tini itself and installed a statically linked binary:after it,
docker-initbecame a symlink to the dynamically linked/usr/bin/tini, and the newSPECS/tini/tini.specbuildstini-staticonly to discard it with%exclude %{_bindir}/tini-static.27.3.1-6and27.3.1-7were an unrelated jq bump and a licence cleanup.master/dev/4.0are unaffected — they still builddocker-initstatically.Upstream moby links
docker-initstatically on purpose:hack/dockerfile/install/tini.installerrunsmake tini-static, and the Dockerfile asserts it withxx-verify --static. Fedora does the same, shipping atini-staticsubpackage thatmoby-enginedepends on.Changes
SPECS/tini/tini.spec(0.19.0-2 → 0.19.0-3)tini-staticin a new subpackage instead of excluding it. The binary is already built and installed into the buildroot by%cmake_build/%cmake_install; the%excludeexisted only to stop RPM's unpackaged-files check from failing the build.tini-disable-git.patch, also dropped by b3da2fa. tini'sCMakeLists.txtoverwritestini_VERSION_GITandgit_version_check_retviaexecute_process(), clobbering the-Dvalues the spec passes. An RPM builds from a tarball with no.git, so the git call fails and the version suffix is silently dropped. moby parsesdocker-init --versionexpectingtini version X.Y.Z - git.COMMIT, sodocker infocurrently reports an emptyinit version:.SPECS/docker/docker.spec(29.8.0-1 → 29.8.0-2) andSPECS/90/docker/docker.spec(28.2.2-7.4.1 → 28.2.2-7.4.2)5.0 gates docker by subrelease —
SPECS/dockerbuilds forphoton_subrelease >= 91,SPECS/90/dockerfor<= 90— and both carry the sameln -srv .../tini .../docker-init, so both are fixed.SPECS/tini/tini.specis not gated, so the singletini-staticsubpackage covers every subrelease.In each:
docker-initattini-static.Requires: tini-static >= 0.19.0-3todocker-engine, the subpackage that actually ships/usr/bin/docker-init.The version bound is deliberate. I simulated an upgrade in which
docker-enginelands while an oldertiniwithouttini-staticis installed: the dangling symlink reproduces the identical error message, so an unversioned dependency would leave that window open.Requires: tinistays on thedockermetapackage.dockeris currently the only package requiringtini, so removing it would orphan/usr/bin/tinitotdnf autoremove— out of scope for this fix.Verification
Built both packages and confirmed:
With
docker-initsymlinked totini-staticexactly as the spec creates it:Note on scope of testing: the RPM build was done locally, not through the Photon build system, so a builder run is still worth doing before merge.
The build and runtime checks above were done on docker 29.5.3. The branch has since been rebased onto 29.8.0 (f7e204f); the two lines this PR changes in
docker.specare identical in 29.8.0, and the spec passes the spec checker, but it has not been rebuilt against 29.8.0.