Skip to content

docker compose publish ignores insecure/localhost registry and routes through proxy (proxyconnect ./pipe/dockerHttpProxy) #13824

@ptrdom

Description

@ptrdom

Description

docker compose publish to a localhost (insecure, plain-HTTP) registry fails on Docker Desktop because the publish client routes the registry request through Docker Desktop's transparent HTTP proxy (named pipe dockerHttpProxy) instead of connecting directly.

docker push / docker pull to the same registry work fine — the registry is correctly recognized as insecure (docker info lists 127.0.0.0/8 under Insecure Registries). Only docker compose publish is affected.

Current behavior — with --insecure-registry, publish switches to http:// but then fails:

failed to do request: Head "http://localhost:5000/v2/spike-app/blobs/sha256:...":
proxyconnect tcp: open ./pipe/dockerHttpProxy: The system cannot find the path specified.

Two things are wrong:

  1. The proxy is not bypassed for localhost. The daemon proxy is http.docker.internal:3128 with No Proxy: hubproxy.docker.internal — localhost/127.0.0.1 are not excluded, and compose publish applies the proxy to the localhost target. It does not honor NO_PROXY/HTTP_PROXY env vars, nor Docker Desktop's proxy-exclude list (verified below).
  2. The proxy named-pipe path is malformed. The error shows a relative ./pipe/dockerHttpProxy, not the real pipe \\.\pipe\dockerHTTPProxy, so the npipe:// proxy URL appears to be mis-parsed and dialed as a file path.

Expected behaviordocker compose publish connects directly to the localhost/insecure registry (as docker push does) and publishes the compose artifact, without going through the proxy.

Steps To Reproduce

Steps To Reproduce

Both shells below were run on the same Windows 11 + Docker Desktop host and produce identical results — so this is not shell- or WSL-specific. docker push succeeds; docker compose publish fails either way. (I have not tested on a native Linux/macOS host.)

  • Git Bash — MSYS2 / MINGW64, GNU bash 5.2.26
  • PowerShell — Windows PowerShell 5.1

In both, docker is the Windows Docker Desktop CLI (C:\Program Files\Docker\Docker\resources\bin\docker).

Git Bash (MSYS2 / MINGW64):

# 1. Plain-HTTP registry on localhost
docker run -d -p 5000:5000 --name registry registry:3

# 2. Seed an image (proves registry + insecure-HTTP path are fine)
docker pull alpine:3.20
docker tag alpine:3.20 localhost:5000/spike-alpine:1
docker push localhost:5000/spike-alpine:1          # ✅ succeeds

# 3. Minimal compose file referencing that image
cat > compose.yaml <<'EOF'
name: spike
services:
  app:
    image: localhost:5000/spike-alpine:1
    command: ["sleep", "3600"]
EOF

# 4. Publish the compose application to the same registry
docker compose -f compose.yaml publish localhost:5000/spike-app:1 --insecure-registry -y
# ❌ proxyconnect tcp: open ./pipe/dockerHttpProxy: The system cannot find the path specified.

PowerShell (Windows / Docker Desktop):

# 1. Plain-HTTP registry on localhost
docker run -d -p 5000:5000 --name registry registry:3

# 2. Seed an image (proves registry + insecure-HTTP path are fine)
docker pull alpine:3.20
docker tag alpine:3.20 localhost:5000/spike-alpine:1
docker push localhost:5000/spike-alpine:1          # ✅ succeeds

# 3. Minimal compose file referencing that image
@'
name: spike
services:
  app:
    image: localhost:5000/spike-alpine:1
    command: ["sleep", "3600"]
'@ | Set-Content -Encoding utf8 compose.yaml

# 4. Publish the compose application to the same registry
docker compose -f compose.yaml publish localhost:5000/spike-app:1 --insecure-registry -y
# ❌ proxyconnect tcp: open ./pipe/dockerHttpProxy: The system cannot find the path specified.

What I observed across variants:

Command Result
docker push localhost:5000/... ✅ succeeds (direct, insecure-HTTP auto-trusted)
docker compose publish ... (no flag) ❌ tries https://localhost:5000 (publish defaults to HTTPS)
docker compose publish ... --insecure-registry ❌ switches to http://, then proxyconnect ... open ./pipe/dockerHttpProxy
same + HTTP_PROXY= / NO_PROXY=localhost,127.0.0.1 ❌ identical error — env ignored
same + bogus HTTP_PROXY=http://127.0.0.1:9 ❌ still uses ./pipe/dockerHttpProxy — confirms env not consulted
after Docker Desktop → Proxies → exclude localhost,127.0.0.1 + restart ❌ unchanged; docker info still shows No Proxy: hubproxy.docker.internal

Compose Version

$ docker compose version
Docker Compose version v5.1.4

$ docker-compose version
Docker Compose version v5.1.4

Docker Environment

Client:
 Version:    29.5.2
 Context:    desktop-linux
 Plugins:
  buildx: Docker Buildx (Docker Inc.)  Version: v0.34.0-desktop.1
  compose: Docker Compose (Docker Inc.)  Version: v5.1.4

Server:
 Server Version: 29.5.2
 Storage Driver: overlayfs (io.containerd.snapshotter.v1)
 Cgroup Version: 2
 Kernel Version: 6.6.114.1-microsoft-standard-WSL2
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 Name: docker-desktop
 HTTP Proxy: http.docker.internal:3128
 HTTPS Proxy: http.docker.internal:3128
 No Proxy: hubproxy.docker.internal
 Labels:
  com.docker.desktop.address=npipe://\\.\pipe\docker_cli
 Insecure Registries:
  hubproxy.docker.internal:5555
  ::1/128
  127.0.0.0/8
 Live Restore Enabled: false


Host: Windows 11. Docker Desktop with WSL2 backend.

Anything else?

  • The named pipe actually exists as \\.\pipe\dockerHTTPProxy, but the dialer reports the relative path ./pipe/dockerHttpProxy — so this looks like an npipe:// proxy-URL parsing/dialing bug in the publish transport, in addition to the missing localhost bypass.
  • Related: Add support for "insecure" registries #13352 (insecure-registry support for publish) added --insecure-registry / __TEST__INSECURE__REGISTRY__. That part works (it switches the scheme to HTTP); this issue is the remaining proxy bypass / named-pipe behavior on top of it.
  • No env-var or flag workaround found. docker push is a working alternative; only docker compose publish hits the proxy.

Please let me know if this is a https://github.com/docker/for-win issue and should be reported there, or elsewhere altogether, instead.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions