Docker Error Guide: 'error mounting to rootfs' — Fix Container Mount Setup
Fix Docker 'error mounting to rootfs': resolve missing bind sources, file-vs-directory mismatches, SELinux labels, and read-only paths so the OCI runtime can set up container mounts and start.
- #docker
- #troubleshooting
- #errors
- #runtime
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
error mounting to rootfs is raised by the OCI runtime (runc) while it assembles the container’s root filesystem and applies bind mounts, before the entrypoint ever runs. The container’s spec parsed fine, but when runc tried to actually mount a source path onto a target inside the new root, the kernel refused — usually because the source is missing, the source/target types disagree (file vs directory), SELinux blocks it, or the target path is read-only.
The literal error names the target inside rootfs:
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/host/config.yaml" to rootfs at "/etc/app/config.yaml": mount /host/config.yaml:/etc/app/config.yaml (via /proc/self/fd/6), flags: 0x5000: not a directory: unknown.
Symptoms
- Container creation fails immediately with
error mounting ... to rootfsand an OCI runtime message. - The message ends in
not a directory,no such file or directory,permission denied, orread-only file system. - A bind mount that worked before starts failing after the host source was deleted or changed from a file to a directory (or vice versa).
- Only containers with a specific
-v/--mountfail; removing that mount lets the container start.
Common Root Causes
- File-vs-directory mismatch — bind-mounting a host file onto a container directory (or a directory onto a file).
not a directory/not a directory: unknownis the tell. - Missing host source — the bind source path does not exist, so Docker creates an empty directory and the type mismatches, or the mount fails with
no such file or directory. - SELinux denial — on RHEL/Fedora, an unlabeled host path is blocked; the mount needs a
:z/:Zrelabel or a policy exception. - Read-only target path — mounting onto a path under a read-only root filesystem or an already read-only mount.
- Target parent missing in image — the destination’s parent directory does not exist in the image and cannot be created.
- Nested/duplicate mount conflict — two mounts targeting overlapping paths in an incompatible order.
Diagnostic Workflow
Read the full runc message — the to rootfs at "<target>" and trailing reason pinpoint the cause:
docker run ... 2>&1 | tail -5
journalctl -u docker --since '5 min ago' | grep -i 'rootfs\|oci runtime'
Verify the host source exists and check its type against the container target’s type:
ls -ld /host/config.yaml # file or directory?
docker run --rm <image> ls -ld /etc/app/config.yaml # what the image has there
If not a directory appears, the source and target types disagree — decide which should be a file.
Check for SELinux on RHEL-family hosts:
getenforce
sudo ausearch -m avc -ts recent | grep -i docker
ls -Z /host/config.yaml
Confirm the target is not on a read-only mount:
docker inspect --format '{{.HostConfig.ReadonlyRootfs}}' <container>
Example Root Cause Analysis
A service failed to start after a config refactor with:
error mounting "/opt/app/config.yaml" to rootfs at "/etc/app/config.yaml" ... not a directory: unknown
ls -ld /opt/app/config.yaml showed the host path was a directory (an earlier docker run had auto-created it as a directory when the real file was missing), while the image expected /etc/app/config.yaml to be a file. runc refused to bind a directory onto a file target.
The fix was to remove the stray auto-created directory and place the actual config.yaml file at the source path, so both sides were files. To prevent recurrence, the team switched to --mount type=bind,source=/opt/app/config.yaml,target=/etc/app/config.yaml, which errors clearly when the source does not exist instead of silently creating an empty directory as -v does.
Prevention Best Practices
- Ensure the host source exists and matches type (file→file, dir→dir) before running; the
-vflag silently creates missing sources as directories, causing type mismatches. - Use
--mountinstead of-vso a missing bind source fails loudly rather than being auto-created wrong. - Add
:z/:Zon SELinux hosts for bind mounts, or set the correct context, so relabeling does not block the mount. - Create destination parents in the image (
RUN mkdir -p) when mounting to nested paths. - Avoid mounting onto read-only roots; mount writable paths as tmpfs or dedicated volumes instead.
- Keep config-file mounts explicit and versioned so a file never gets replaced by a directory by accident.
Quick Command Reference
ls -ld /host/source/path # confirm source type/existence
docker run --rm <image> ls -ld /container/target # confirm target type in image
getenforce; ls -Z /host/source/path # SELinux status + label
sudo ausearch -m avc -ts recent | grep docker # SELinux denials
docker run --mount type=bind,source=/abs/file,target=/etc/app/config.yaml img
docker run -v /abs/dir:/data:Z img # SELinux-relabeled bind
Conclusion
error mounting to rootfs is runc failing to set up a bind mount during container init — the spec was valid, the kernel-level mount was not. Read the target path and trailing reason: not a directory means a file/dir type mismatch, no such file means a missing source, and SELinux or read-only targets each have their own tell. Make sources exist with the right type, prefer --mount, and relabel for SELinux. For volume-source mount failures, see the failed to mount local volume guide and the full Docker guides.
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.