Skip to content
DevOps AI ToolKit
Newsletter
All guides
Docker with AI By James Joyner IV · · 8 min read

Docker Error Guide: 'mkdir: read-only file system' — Fix Read-Only Containers and Mounts

Quick answer

Fix Docker 'mkdir read-only file system': diagnose --read-only containers, read-only bind mounts, and writes to immutable image layers, then add writable volumes or tmpfs correctly.

Part of the Docker Container & Runtime Errors hub
  • #docker
  • #troubleshooting
  • #errors
  • #volumes
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

An application inside a container tries to create a directory (or write a file) and the kernel rejects it because the target path is mounted read-only:

mkdir /app/cache: read-only file system

The EROFS error means the filesystem backing that path does not permit writes. In Docker this usually comes from a hardened --read-only container, a bind mount added with the :ro flag, or an attempt to write into a location that overlaps a read-only mount.

Symptoms

  • The app logs read-only file system when it tries to create a temp dir, log file, or cache.
  • The container starts but crashes the moment it writes to disk.
  • The same image works without --read-only but fails once security hardening is enabled.
  • A process can read a mounted config but cannot write next to it.

Common Root Causes

  • --read-only root filesystem — the container was started with a read-only root for security, and the app writes somewhere without a writable volume.
  • Read-only bind mount — a volume was added with :ro (or read_only: true in Compose) but the app needs to write to it.
  • Writing under a read-only mount point — the app writes to a subpath of a directory mounted read-only.
  • Read-only secrets/config mounts — Kubernetes configMap/secret mounts and Docker configs are read-only by design.
  • Immutable image layers — attempting to modify files baked into a lower overlay layer in an unexpected way.

Diagnostic Workflow

Check whether the container’s root filesystem was made read-only:

docker inspect --format 'ReadonlyRootfs={{.HostConfig.ReadonlyRootfs}}' myapp

List every mount and its RW/RO flag:

docker inspect --format '{{range .Mounts}}{{.Type}} {{.Source}} -> {{.Destination}} rw={{.RW}}{{println}}{{end}}' myapp

From inside the container, see exactly which mount owns the failing path and whether it is ro:

docker exec -it myapp sh -c 'mount | grep " /app "; touch /app/cache/.probe 2>&1'

A ro in the mount options, or Read-only file system from the touch, confirms it. Check the Compose/run configuration for the flags that caused it:

docker inspect --format '{{json .HostConfig.Tmpfs}}' myapp

Example Root Cause Analysis

After a security review, a service was hardened with --read-only to prevent tampering. It immediately crash-looped with mkdir /app/cache: read-only file system.

Inspecting confirmed the read-only root:

docker inspect --format '{{.HostConfig.ReadonlyRootfs}}' myapp
# true

The application wrote scratch data to /app/cache at startup. With the root filesystem read-only, that write failed. The correct fix was to keep the hardened read-only root but provide writable space exactly where the app needs it — a tmpfs for ephemeral cache and a named volume for anything that must persist:

docker run --read-only \
  --tmpfs /app/cache:rw,size=64m \
  -v app-data:/app/data \
  myapp:1.4.2

The container kept its immutable root filesystem for security while /app/cache and /app/data became writable, and the crash loop stopped.

Prevention Best Practices

  • When using --read-only, explicitly mount writable tmpfs for scratch/cache paths and named volumes for persistent data.
  • Design images to write only to well-defined, documented directories so writable mounts are easy to provision.
  • Do not add :ro to a mount the application needs to write; reserve read-only for config and secrets.
  • In Compose, pair read_only: true with a tmpfs: list and volume mounts for the writable paths.
  • Validate mount and volume declarations with the Dockerfile validator and follow storage patterns in the Docker stack guide.

Quick Command Reference

docker inspect --format '{{.HostConfig.ReadonlyRootfs}}' myapp        # read-only root?
docker inspect --format '{{range .Mounts}}{{.Destination}} rw={{.RW}}{{println}}{{end}}' myapp
docker exec -it myapp sh -c 'mount | grep " /app "'                   # which mount, ro or rw?
docker run --read-only --tmpfs /app/cache:rw,size=64m -v app-data:/app/data myapp:1.4.2

Conclusion

mkdir: read-only file system is EROFS — the app is writing to a path that is mounted read-only. The cause is almost always a --read-only container or a :ro mount, not a bug in the app. Inspect the container’s ReadonlyRootfs flag and its mounts, find which mount owns the failing path, and provide a writable tmpfs or volume exactly where writes are needed. That keeps your security hardening intact while letting the application do its job.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.