Mounting /var/run/docker.sock gives the container full use of the Docker API. Anyone who controls that container can start a new privileged container with the host's root filesystem mounted, which is a takeover of the host. A read-only mount does not change this. The explainer marks it critical, and also flags mounts of /, /var, /var/run or /run, which contain the socket.
openrouting — compose explainer
$ explain docker-compose.yml! proxy mounts the Docker socket criticalline 9fix: see below$
What the free Docker Compose explainer reports on the risky example below.
Why it matters
The Docker socket is the API of the Docker daemon, and the daemon runs as root. Docker's own documentation warns that only trusted users should be able to control it, because access to the daemon amounts to root on the host.
Adding `:ro` only stops the container from changing the socket file. It can still connect and send API requests, so it can still create, start and exec into containers.
The mount is common in reverse proxies, CI runners, dashboards and backup tools that watch other containers. If one of those is exposed to the network and has a bug, the bug is a path to the host.
services:
proxy:
image: traefik:v3.1.6
# Routes come from files in the repository instead of the Docker API
command:
- --providers.file.directory=/etc/traefik/dynamic
ports:
- "80:80"
volumes:
- ./traefik/dynamic:/etc/traefik/dynamic:ro
restart: unless-stopped
mem_limit: 512m
How to fix it
Check whether the service has a mode that does not need the Docker API, such as file-based configuration, and use it.
If it must talk to Docker, put a socket proxy in front of the daemon that allows only the API calls it uses (often read-only listing of containers), and point the service at the proxy with DOCKER_HOST.
Never mount /, /var, /var/run or /run as a shortcut: they contain the socket too, and the explainer flags them for that reason.
When it's acceptable
Tools whose whole job is to manage containers on that host (a CI runner on a dedicated build machine, a local development dashboard) and that you trust to have root on it.
The socket proxy service itself, which has to mount the socket; the explainer will still flag it, and that line is the one to review carefully.
Check your own docker-compose.yml
The risky example is loaded below. Paste your own file to check it for this and every other Docker Compose rule. It runs in your browser; nothing is uploaded.
Limits memory to 512m. The container is killed if it exceeds this.
Questions
Is mounting docker.sock read-only safe?
No. The :ro flag only stops writes to the socket file. The container can still connect to it and send any Docker API request, including starting a privileged container.
Why is access to the Docker socket the same as root?
The Docker daemon runs as root and will start any container it is asked to, including one that mounts the host's root filesystem or runs privileged. Whoever can talk to the socket can ask for that.
How do I let a container see other containers without docker.sock?
Use a socket proxy that exposes only the read-only endpoints the service needs, or switch the service to a configuration mode that does not use the Docker API at all.