Docker socket proxy
A Docker socket proxy is a small service that sits between a tool and /var/run/docker.sock and forwards only the Docker API requests you explicitly allow, rejecting the rest. It lets monitoring, reverse proxy or CI tools read what they need without receiving the full root-equivalent control that the raw socket gives.
What problem a Docker socket proxy solves
The Docker daemon runs as root, so whoever can talk to its socket controls the host. The OWASP Docker Security Cheat Sheet says granting that access is equivalent to unrestricted root access, that Docker grants all daemon commands by default, and that a read-only mount does not make the API read-only. The basics are in our Docker socket entry.
Yet many tools want the socket, typically to list containers or watch events. A socket proxy removes the all-or-nothing choice. The tool talks to the proxy, the proxy talks to the socket, and every request is checked against an allow list first. A tool that only needs to discover containers then cannot start, stop or create anything, even if it is compromised or misbehaves. The idea is least privilege applied to an API, as described in least privilege.
How Tecnativa docker-socket-proxy works
According to the project README, it is a small HAProxy configuration on the official Alpine HAProxy image that answers dangerous requests with HTTP 403 Forbidden. You grant or revoke API sections with environment variables, 1 to grant and 0 to revoke. By default EVENTS, PING and VERSION are granted, while sections such as CONTAINERS, IMAGES, EXEC, VOLUMES and SERVICES are revoked, and AUTH, SECRETS and POST are called security-critical. With POST off, only GET and HEAD requests pass.
A compose sketch adapted from the README's docker run example:
services:
socket-proxy:
image: tecnativa/docker-socket-proxy
privileged: true
environment:
CONTAINERS: 1
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks: [socket_net]
networks:
socket_net:
internal: true
Attach the client to socket_net and set DOCKER_HOST=tcp://socket-proxy:2375. The README says --privileged is required because of how the socket connection works.
What a socket proxy does not protect against
The proxy narrows access; it does not remove risk. Three limits matter.
First, the proxy has no TLS and no login. The README says never to expose its port to a public network, so keep it on an internal Docker network shared only with its one client, or bound to 127.0.0.1 as in the README's example.
Second, the proxy container itself mounts the real socket, so a flaw in it is still a path to root.
Third, what you enable still counts. Its published HAProxy rules key off the HTTP method and URL path, so it cannot tell a harmless container call from a dangerous one on the same endpoint. Enabling POST with CONTAINERS lets a client create containers, which is root-equivalent, as the Docker host security guide explains. Even read access leaks data: inspecting a container reveals its environment variables, which often hold secrets. Enable the smallest set of sections and treat EXEC, POST, BUILD and SERVICES as potentially root-level.
Alternatives to exposing the socket
The best option is not to give a tool the socket at all. If it can be configured statically, or can receive container information another way, do that. For your own administration, use a Docker context over SSH instead of a TCP listener; the Docker documentation notes that the SSH user still needs permission to use the socket, and that anyone holding the keys of a TLS-exposed daemon has root on the host.
Rootless mode attacks the problem from another side. According to the rootless mode documentation, it exists to mitigate potential vulnerabilities in the daemon and the container runtime, and the socket then lives under the user's runtime directory, for example /run/user/1000/docker.sock. OWASP adds that it does not protect against host privilege escalation through kernel vulnerabilities. The two approaches address different things, so combine them with the host checks in the Docker guide and the access rules from UID 0.
Related terms: Docker socket, Least privilege, UID 0, Firewall.
Frequently asked questions
What is a Docker socket proxy?
It is a filter that sits in front of /var/run/docker.sock and forwards only the Docker API requests you allow, returning an error such as HTTP 403 for the rest. Tools then get limited access instead of full control of the daemon.
Which API sections does Tecnativa docker-socket-proxy allow by default?
Per its README, EVENTS, PING and VERSION are granted by default. AUTH, SECRETS, POST and sections such as CONTAINERS, IMAGES and EXEC are revoked until you set the matching variable to 1.
Is mounting docker.sock read-only enough instead of a proxy?
No. OWASP states that mounting the socket read-only does not make the Docker API read-only, so a container can still issue powerful commands. A proxy filters the requests themselves.
Does a socket proxy make a compromised tool harmless?
No. It limits the calls the tool can make, but whatever you enable remains available, and enabling POST with CONTAINERS lets a client create containers, which is root-equivalent. Allow the minimum and keep the proxy on a private network.
Does the proxy encrypt or authenticate connections?
The README says it has no TLS support and uses plain HTTP, and it describes no client authentication. Restrict who can reach its port with Docker networks and never expose it publicly.
Want to see where your own server stands?
Run the free, read-only server check, or open the Security Lab and watch the detect, contain, recover, verify loop in action.
Get your free server checkOpen the Security Lab