Skip to content

fix(publish): bypass Docker Desktop proxy for localhost/insecure registries#13825

Open
ptrdom wants to merge 2 commits into
docker:mainfrom
ptrdom:fix/publish-localhost-proxy-bypass
Open

fix(publish): bypass Docker Desktop proxy for localhost/insecure registries#13825
ptrdom wants to merge 2 commits into
docker:mainfrom
ptrdom:fix/publish-localhost-proxy-bypass

Conversation

@ptrdom
Copy link
Copy Markdown

@ptrdom ptrdom commented Jun 7, 2026

What I did

docker compose publish routed all registry traffic through Docker Desktop's HTTP proxy. Publishing to a localhost/insecure registry therefore failed on Windows with:

proxyconnect tcp: open ./pipe/dockerHttpProxy: The system cannot find the path specified.

even though docker push/docker pull worked against the same registry.

Two bugs in internal/desktop/proxy.go:

  1. No loopback bypass. ProxyTransport forced every request through the DD proxy and its DialContext always dialed the proxy socket, so loopback targets could never connect directly. Proxy selection now goes through httpproxy.Config.ProxyFunc, which exempts localhost/loopback and additionally honors NO_PROXY. DialContext routes only the sentinel proxy address to the DD socket and dials real targets directly otherwise.
  2. Malformed Windows pipe path. The proxy named-pipe endpoint was hardcoded as npipe://./pipe/..., yielding the relative path ./pipe/dockerHttpProxy. It is now derived from the engine endpoint, preserving its namespace. Docker Desktop reports the endpoint in the backslash form npipe://\\.\pipe\docker_cli, so the derivation uses LastIndexAny to handle both backslash and forward-slash forms.

Result: publishing to localhost:5000 connects directly like docker push, while the DD proxy still serves external registries (now reachable on Windows).

Related issue

Fixes #13824

How I tested

Validated end-to-end on Docker Desktop 29.5.2 / Windows 11 (the issue's environment) by building binaries from both the parent commit and this branch and running the issue's reproduction steps:

# start a plain-HTTP localhost registry
docker run -d -p 5000:5000 --name registry registry:3

# minimal compose.yaml referencing any pushable image, then publish
# (spike-app is the placeholder image name from #13824's repro steps)
docker compose publish localhost:5000/spike-app:1 --insecure-registry -y
  • Parent commit: reproduces the issue verbatim — proxyconnect tcp: open ./pipe/dockerHttpProxy: The system cannot find the path specified. (exit 1).
  • This branch: publishes successfully (exit 0); the artifact lands in the localhost registry.

Automated coverage in internal/desktop/proxy_test.go:

  • TestDDProxyFunc_BypassesLoopbackAndHonorsNoProxy — loopback names/IPs and NO_PROXY hosts bypass; external hosts proxy.
  • TestHTTPProxySocketEndpoint_WindowsNamedPipe — proxy pipe path keeps the engine endpoint's namespace for both backslash and forward-slash forms.

🤖 Generated with Claude Code

ptrdom and others added 2 commits June 7, 2026 15:14
…stries

compose publish routed all registry traffic through Docker Desktop's HTTP
proxy, so publishing to a localhost/insecure registry failed on Windows
with "proxyconnect tcp: open ./pipe/dockerHttpProxy: The system cannot
find the path specified", while docker push/pull worked against the same
registry.

Two bugs in internal/desktop/proxy.go:

- ProxyTransport forced every request through the DD proxy and its
  DialContext always dialed the proxy socket, so loopback targets could
  never connect directly. Select the proxy via httpproxy.Config.ProxyFunc,
  which exempts localhost/loopback and now also honors NO_PROXY; route
  only the sentinel proxy address to the DD socket and dial real targets
  directly otherwise.

- The Windows named-pipe endpoint was hardcoded as npipe://./pipe/...,
  yielding the relative path ./pipe/dockerHttpProxy. Derive it from the
  engine endpoint, preserving the dialable npipe:////./pipe/ prefix.

Fixes docker#13824

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Domantas Petrauskas <dom.petrauskas@gmail.com>
End-to-end validation against Docker Desktop 29.5.2 showed it reports its
engine endpoint as `npipe://\.\pipe\docker_cli` (backslash namespace),
not the forward-slash form assumed earlier. LastIndex(endpoint, "/") then
matched the slash in "npipe://" and produced `npipe://dockerHttpProxy`,
dropping the `\.\pipe\` namespace.

Use LastIndexAny(endpoint, `/\`) so both the backslash form Docker Desktop
actually reports and the forward-slash form resolve to a dialable pipe
path. Verified the published artifact lands in a localhost registry and
that the parent commit still reproduces the original
"proxyconnect tcp: open ./pipe/dockerHttpProxy" failure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Domantas Petrauskas <dom.petrauskas@gmail.com>
@ptrdom ptrdom requested a review from a team as a code owner June 7, 2026 13:05
@ptrdom ptrdom requested review from glours and ndeloof June 7, 2026 13:05
@ptrdom
Copy link
Copy Markdown
Author

ptrdom commented Jun 7, 2026

I have also manually tested this on MacOS (M1 Mac) with Docker Desktop, managed to reproduce the issue and confirmed that this PR fixes it.

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 compose publish ignores insecure/localhost registry and routes through proxy (proxyconnect ./pipe/dockerHttpProxy)

1 participant