Fixing Docker Daemon “404 Page Not Found” Error After Version Upgrade: Proxy Conflicts and Socket Communication


2 views

When I upgraded from Docker 1.4 to 1.5 using the lxc_docker package, I encountered this puzzling scenario:

$ docker version
Client version: 1.5.0
Client API version: 1.17
FATA[0000] Error response from daemon: 404 page not found

Yet the old client worked perfectly:

$ /usr/bin/docker-old version
Server version: 1.5.0
Server API version: 1.17

The root cause lies in how Docker 1.5 handles local socket communication when proxy environment variables (HTTP_PROXY, HTTPS_PROXY) are present. The newer version attempts to route UNIX socket communication through the proxy, which obviously fails.

While setting NO_PROXY works:

export NO_PROXY="/var/run/docker.sock"

More robust solutions include:

# Option 1: System-wide docker configuration
echo 'export NO_PROXY="/var/run/docker.sock,$NO_PROXY"' >> /etc/profile.d/docker_proxy.sh

# Option 2: Docker systemd unit override
mkdir -p /etc/systemd/system/docker.service.d
cat << EOF > /etc/systemd/system/docker.service.d/proxy.conf
[Service]
Environment="NO_PROXY=/var/run/docker.sock"
EOF
systemctl daemon-reload
systemctl restart docker

To inspect the actual API call flow:

strace -f -e trace=network docker version 2>&1 | grep connect

For developers creating Docker clients, always handle these cases:

func getDockerClient() (*client.Client, error) {
    if os.Getenv("HTTP_PROXY") != "" {
        if _, err := os.Stat("/var/run/docker.sock"); err == nil {
            return client.NewClientWithOpts(
                client.WithHost("unix:///var/run/docker.sock"),
                client.WithHTTPClient(&http.Client{
                    Transport: &http.Transport{
                        Proxy: nil, // Explicitly disable proxy for UNIX sockets
                    },
                }),
            )
        }
    }
    return client.NewClientWithOpts(client.FromEnv)
}

When upgrading from Docker 1.4 to 1.5, many users encounter this puzzling behavior:

$ docker ps
FATA[0000] Error response from daemon: 404 page not found

Yet oddly, the old client binary works perfectly:

$ /usr/bin/docker-old images
REPOSITORY          TAG                 IMAGE ID            CREATED

The core issue stems from how Docker 1.5+ handles API routing through Unix sockets when HTTP_PROXY is set:

  1. New versions attempt to route unix:///var/run/docker.sock through HTTP proxies
  2. The proxy tries to handle Unix socket connections as HTTP requests
  3. Daemon receives malformed requests, returning 404 errors

Method 1: NO_PROXY Configuration

The cleanest approach is modifying your environment variables:

# Add to ~/.bashrc or systemd service file
export NO_PROXY="localhost,127.0.0.1,/var/run/docker.sock"

Method 2: Daemon Configuration

For systemd deployments, create an override file:

# /etc/systemd/system/docker.service.d/override.conf
[Service]
Environment="NO_PROXY=/var/run/docker.sock"

Method 3: Client Flag (Temporary)

For quick testing, use the direct socket flag:

docker -H unix:///var/run/docker.sock version

This behavior affects:

  • Docker 1.5.0 through 1.12.x
  • Occurs with both HTTP_PROXY and HTTPS_PROXY
  • More prevalent in corporate environments with strict proxy rules

Confirm your fix worked with:

env | grep -i proxy
curl --unix-socket /var/run/docker.sock http://localhost/version