You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(docker): direct-exec resolved docker binary for isolated spawn (MCP-2753) (#703)
* fix(docker): direct-exec resolved docker binary for isolated spawn (MCP-2753)
PR #697 resolved the docker CLI to an absolute path but still routed the
isolated spawn through `$SHELL -l -c "<docker> run …"`, where the login shell
re-derives $PATH from rc files and can drop the Docker Desktop bundle dir. The
absolute path was only a token in the -c string, so docker-isolated servers
still failed with `command not found: docker` when the CLI was not on the
LaunchAgent/tray spawn PATH — even though `upstream_servers list` reported a
good docker_path.
On successful resolution to a VERIFIED absolute executable, setupDockerIsolation
now returns the resolved binary as the exec command with raw docker argv (no
shell wrap), mirroring the management path's newDockerCmd. It returns a
shellWrapped flag so callers pick the matching cidfile helper: the new
args-based insertCidfileIntoDockerArgs inserts `--cidfile` after the `run`
token (platform-agnostic, sidestepping the -c vs /c quirk), while the
login-shell fallback keeps the string-based insertCidfileIntoShellDockerCommand.
The direct-exec branch is gated by isDirectExecutable (filepath.IsAbs + os.Stat
+ exec-bit). ResolveDockerPath's last resort runs `command -v docker` in the
login shell, which can emit a shell function/alias/bare name; such a value is
rejected and shell-wrapped instead of failing a direct exec. Login-shell wrap of
bare `docker` is also kept on the resolution-failure fallback.
The DOCKER_* daemon-env half of MCP-2753 is already satisfied by the startup
login-shell hydration shipped in MCP-2751 (#701): DOCKER_* are hydrated into
os.Environ() and carried through BuildSecureEnvironment's default allow-list, so
the direct-exec'd docker process still reaches Colima/rootless/remote daemons
without a per-spawn shell capture.
Related #699
Related #696
* fix(docker): gate direct-exec on guaranteed daemon env (non-Darwin rootless regression)
Codex round-4 (PR #703 REQUEST_CHANGES, P2): the direct-exec branch regressed
non-Darwin rootless/remote Docker. Dropping the `$SHELL -l` wrap also drops
rc-file env inheritance, and HydrateFromLoginShell (MCP-2751) is Darwin-only
while BuildSecureEnvironment only forwards DOCKER_* already in os.Environ(). So
on Linux a daemon whose DOCKER_HOST/DOCKER_CONTEXT lives only in .profile would
be lost by direct-exec — the same DOCKER_* loss that made #699 keep the shell
wrap.
Add a second precondition (dockerDaemonEnvGuaranteed) alongside the verified-
absolute-executable check: direct-exec only when the daemon env is guaranteed
without the login shell — macOS (startup hydration captured DOCKER_* into
os.Environ()) OR DOCKER_HOST/DOCKER_CONTEXT already present in the process env on
any platform. Otherwise keep the `$SHELL -l` wrap so `docker run` inherits the
rc-file daemon config; the wrap now prefers the resolved absolute path (still
sidestepping the login shell's PATH re-derivation) and drops to bare "docker"
only when resolution failed.
dockerDaemonEnvGOOS is a package var so the Darwin branch is testable on a
non-Darwin CI host. New tests: non-Darwin + DOCKER_HOST-only-in-rc stays
shell-wrapped with the absolute path; non-Darwin + DOCKER_HOST in env direct-
execs; and a table test for the gate.
Related #703
Related #699
Co-Authored-By: Paperclip <noreply@paperclip.ing>
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
c.logger.Warn("Could not resolve docker to an absolute path; falling back to bare 'docker' via login shell (isolated server may fail if docker is not on the spawn PATH)",
116
+
zap.String("server", c.config.Name),
117
+
zap.Error(resErr))
118
+
case!isDirectExecutable(resolved):
119
+
c.logger.Warn("Resolved docker value is not a verified absolute executable; falling back to login-shell wrap",
120
+
zap.String("server", c.config.Name),
121
+
zap.String("resolved", resolved))
122
+
default:
123
+
// Verified absolute executable, but the daemon env is not guaranteed
124
+
// without the login shell (non-Darwin, no DOCKER_HOST/DOCKER_CONTEXT in
125
+
// os.Environ()). Keep the shell wrap so rc-file DOCKER_* are inherited.
126
+
c.logger.Debug("docker daemon env not guaranteed in process env; keeping login-shell wrap so rc-file DOCKER_* are inherited",
c.logger.Warn("Could not resolve docker to an absolute path; falling back to bare 'docker' (isolated server may fail if docker is not on the spawn PATH)",
0 commit comments