Podman closes an idle API connection after twice its service_timeout, 10s by
default, and advertises no Keep-Alive header. DefaultConnectionKeepAliveStrategy
therefore falls back to RequestConfig's 3-minute default, so the pool keeps
handing out connections the daemon dropped long ago. Revalidation on lease is
disabled (c61da29, for docker-java#1726) and HttpClient5 will not retry a POST, so
/containers/create and /containers/{id}/exec surface the dead connection to the
caller as "NoHttpResponseException: localhost:2375 failed to respond".
Set a connection keep-alive fallback so an idle connection is expired before any
known daemon's window can close it. It is a fallback rather than a ceiling: a
peer that advertises its own Keep-Alive timeout is still honoured.
Tests come in two layers. IdleConnectionReuseTest drives a fake daemon over
tcp:// and needs no docker at all; IdleConnectionReuseIT runs against whatever
DOCKER_HOST points at and skips unless a raw-socket probe shows the daemon
actually hangs up on idle connections, which it does not on docker.
Fixes docker-java#2682
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WCQ8B2RchzdWf7xbhkaXQr
Signed-off-by: David Tavoularis <david.tavoularis@mycom-osi.com>
Podman closes an idle API connection after twice its service_timeout, 10s by default, and advertises no Keep-Alive header. DefaultConnectionKeepAliveStrategy therefore falls back to RequestConfig's 3-minute default, so the pool keeps handing out connections the daemon dropped long ago. Revalidation on lease is disabled (c61da29, for #1726) and HttpClient5 will not retry a POST, so /containers/create and /containers/{id}/exec surface the dead connection to the caller as "NoHttpResponseException: localhost:2375 failed to respond".
Set a connection keep-alive fallback so an idle connection is expired before any known daemon's window can close it. It is a fallback rather than a ceiling: a peer that advertises its own Keep-Alive timeout is still honoured.
Tests come in two layers. IdleConnectionReuseTest drives a fake daemon over tcp:// and needs no docker at all; IdleConnectionReuseIT runs against whatever DOCKER_HOST points at and skips unless a raw-socket probe shows the daemon actually hangs up on idle connections, which it does not on docker.
Fixes #2682