Skip to content

feat: Find Docker through the current context and add --docker-timeout - #76

Merged
nealrichardson merged 3 commits into
mainfrom
docker-client
Oct 23, 2026
Merged

nealrichardson merged 3 commits into
mainfrom
docker-client

Conversation

@nealrichardson

@nealrichardson nealrichardson commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #42. Fixes #60.

Stacked on #70 (clean-errors), which adds the docker_client() helper this builds on. After #70 is squash-merged, this branch needs a rebase onto main and the PR base retargeted to main.

#42: Docker socket outside /var/run/docker.sock

Problem: docker-py's from_env() reads only DOCKER_HOST and otherwise uses /var/run/docker.sock. Docker Desktop on macOS, Colima, OrbStack, Rancher Desktop and others put the socket somewhere else, so with-connect fails unless the user sets DOCKER_HOST by hand.

Approach: Instead of hardcoding the Docker Desktop path, use the Docker CLI's current context, which is how the docker command finds the daemon. Every one of those tools registers a context pointing at its socket.

  • DOCKER_HOST, if set, always wins.
  • Otherwise the context is DOCKER_CONTEXT if set, else currentContext from the Docker config (respecting DOCKER_CONFIG). docker-py's ContextAPI doesn't read DOCKER_CONTEXT itself, so with-connect passes it in.
  • The context's host is only used when it is a local unix:// or npipe:// socket that differs from the default socket. The default context, tcp:// and ssh:// contexts, and missing or unreadable context files all fall back to plain from_env(), which is what with-connect does today. Remote contexts need TLS certs or SSH options, and supporting those would mean reimplementing more of the CLI. Anyone using one can still set DOCKER_HOST and the DOCKER_TLS_* variables.
  • The host reaches docker-py through from_env(environment=...), a copy of os.environ with DOCKER_HOST set, so the process environment stays unchanged. with-connect -- COMMAND therefore passes the user's environment through untouched.
  • If the context's socket can't be reached, the short error from fix: Report Docker and installed-command errors as a short message #70 names it: Could not connect to Docker at unix:///... (from the current Docker context). Is it running? ...

#60: Docker API timeout fixed at 60 seconds

Problem: docker-py's default per-request timeout is 60 seconds, and with-connect offers no way to change it. On busy CI machines, container create can take longer than that.

Approach:

  • New --docker-timeout SECONDS flag. It takes a positive, finite number and is validated like --port.
  • If the flag isn't given, with-connect reads DOCKER_CLIENT_TIMEOUT, the name docker-compose v1 used for the same setting, so it may already be set in some CI environments. An invalid value is rejected with a usage error that names the variable.
  • The default is 120 seconds. The issue describes create calls crossing 60 seconds on otherwise healthy machines, so doubling the limit avoids most of those failures with no configuration. The cost is that a daemon that has truly hung takes up to two minutes to report it.
  • New docker-timeout action input, passed only when set, in both start and stop modes.
  • README documents the flag, the env var fallback, the action input, and the context-based socket lookup.

Per-call timeouts such as container.stop(timeout=...) are out of scope.

Verification

On this machine (Docker Desktop; current context desktop-linux → unix:///Users/.../.docker/run/docker.sock; /var/run/docker.sock is a symlink to it):

  • With DOCKER_HOST unset, context_docker_host() returns the Docker Desktop socket and docker_client().version() connects (Engine 29.5.3).
  • With a temp DOCKER_CONFIG whose fake context points at the real socket: the socket is resolved, the client connects, and client.api.timeout matches the requested value.
  • DOCKER_CONTEXT set to a context whose socket doesn't exist: with-connect --stop exits 1 with the one-line "Could not connect to Docker at ..." error.
  • DOCKER_CLIENT_TIMEOUT=x: exit 2 with DOCKER_CLIENT_TIMEOUT: invalid timeout value: 'x'.
  • End to end, --docker-timeout 30 with a fake license on a random port: the image pull, container create and start, and log polling all went through the context-resolved client. Connect then rejected the license as expected, and the container was stopped.

Tests

New tests sit next to test_docker_unreachable_is_reported and are registered in the __main__ block. They cover:

  • context resolution from a temp DOCKER_CONFIG
  • DOCKER_CONTEXT taking precedence over currentContext
  • DOCKER_HOST taking precedence over both
  • fallback for the default socket, tcp://, ssh://, no config, a missing context, and a corrupt meta.json
  • docker_client() passing the host and timeout through without changing os.environ
  • the error naming the context socket
  • timeout parsing: default, flag, env var, flag beating env var
  • rejected values: 0, -5, inf, nan, abc, and an invalid env var

The context tests point HOME at the temp dir, because docker-py falls back to ~/.docker/config.json.

uv run test_main.py and uv run --with pytest pytest -q both pass (54 tests).

Conflicts with other open branches

Checked after rebasing onto the updated #70, which is now rebased onto main (including #69, #71, #74, and #75):

🤖 Generated with Claude Code

Base automatically changed from clean-errors to main October 23, 2026 19:06
nealrichardson and others added 3 commits October 23, 2026 15:09
When DOCKER_HOST isn't set, use the socket of the Docker CLI's current
context (DOCKER_CONTEXT, else currentContext in the Docker config), so
Docker Desktop on macOS, Colima, OrbStack and similar work without
setting DOCKER_HOST. Only unix:// and npipe:// context hosts are used;
the default context and tcp:// or ssh:// contexts keep docker-py's
from_env() behavior. The host is passed to from_env() through its
environment argument instead of changing os.environ.

Add --docker-timeout SECONDS (falling back to DOCKER_CLIENT_TIMEOUT)
for the Docker API timeout, with a default of 120 seconds instead of
docker-py's 60, plus a matching docker-timeout action input.

Fixes #42.
Fixes #60.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lines

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nealrichardson

Copy link
Copy Markdown
Collaborator Author

sure, let's see if this helps

@nealrichardson
nealrichardson merged commit dc01489 into main Oct 23, 2026
13 checks passed
@nealrichardson
nealrichardson deleted the docker-client branch October 23, 2026 19:14
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.

Docker timeout is stuck at 60 seconds with no way to raise it Auto-detect Docker Desktop socket location on macOS

1 participant