prefer-read-only-bind-mount
Compose bind mounts are writable by default. When a service only reads a host directory, add :ro or read_only: true so a compromised container cannot change files on the host.
On this page
A Compose bind mount is read-write unless you say otherwise, and most of them never needed to be: certificates, model weights, static assets, and configuration are read by the service and written by you. This rule reports bind mounts whose host source lies outside the Compose project (an absolute path, ~, or ../) and that are not marked read-only, in either the short syntax (:ro) or the long syntax (read_only: true). Relative mounts inside the project (./src:/app/src) are the usual dev-loop mounts and are not reported; neither is the Docker socket, which has its own rule.
What the rule catches
services:
web:
image: nginx:1.27-alpine
volumes:
- /opt/certs:/etc/nginx/certs
- type: bind
source: /srv/site
target: /usr/share/nginx/htmlScanning this file reports:
ℹ INFO [docker-doctor/prefer-read-only-bind-mount]
Service 'web' bind-mounts host path '/opt/certs' read-write. A writable host mount lets the container change files outside the project, and is the foothold for VM-escape bugs like CVE-2026-77179.Why it matters
Read-only is the cheapest hardening a bind mount can get, and it removes a whole class of attack rather than one bug. A container that can write to a host directory can plant files where the host will later execute or trust them. On Docker Desktop and Docker Sandboxes, where containers run in a VM and the mount is served from the host, a writable mount is also the precondition for VM-escape bugs: CVE-2026-77179 needed to create a file, delete its directory, and replace it with a symlink, none of which works on a read-only mount. The isolation that a VM promises holds only for the paths the guest cannot write.
How to fix it
Append :ro to the short syntax, or set read_only: true in the long syntax, unless the service must write to the host path.
services:
web:
image: nginx:1.27-alpine
volumes:
- /opt/certs:/etc/nginx/certs:ro
- type: bind
source: /srv/site
target: /usr/share/nginx/html
read_only: trueAppend :ro to a short-syntax mount, or add read_only: true under a long-syntax one. If the service does write there, ask whether the host directory is really the right place: a named volume keeps the data without exposing a host path at all, and no-broad-bind-mount covers the case where the path is not just writable but far too wide.
The rule reports at info severity, so it does not affect the health score by much on its own. Raise it to warning in docker-doctor.config.json for services that run untrusted code, such as coding agents and CI runners.
Rule details
- Rule key —
docker-doctor/prefer-read-only-bind-mount - Category — Compose
- Default severity —
info - Applies to — Docker Compose files
Explain this rule from the CLI:
npx @docker-doctor/cli@latest rules explain docker-doctor/prefer-read-only-bind-mountChange its severity — or turn it off — in your config file:
// docker-doctor.config.ts
export default {
rules: {
"docker-doctor/prefer-read-only-bind-mount": "off",
},
};Severity affects the health score: error findings cost more points than warning, and info costs the least.