This error occurs when Docker BuildKit cannot create or access a cache mount during the build process. It is typically caused by permission issues, incorrect mount syntax, or file system constraints.
When you see "failed to solve: failed to prepare cache mount: failed to mount" during a Docker build, it means BuildKit encountered a problem setting up the cache directory specified in your `RUN --mount=type=cache` instruction. BuildKit cache mounts are a powerful feature that allows you to persist build-time dependencies (like npm packages, pip caches, or Go modules) between builds. However, they require proper permissions and configuration to function correctly. This error typically points to one of three issues: permission problems where the cache directory cannot be created or written to, syntax errors in the mount instruction, or file system limitations (especially on macOS or Windows with Docker Desktop).
The most common fix is to explicitly set permissions on the cache mount. By default, BuildKit creates cache mounts with restrictive permissions that may not work on all systems.
Update your Dockerfile:
# Before (may fail):
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt
# After (with explicit permissions):
RUN --mount=type=cache,mode=0777,target=/root/.cache/pip pip install -r requirements.txtThis is especially important on macOS and Windows Docker Desktop where the default mode may prevent mounting.
Cache mounts require BuildKit and the appropriate Dockerfile syntax version. Add this directive at the very beginning of your Dockerfile:
# syntax=docker/dockerfile:1
FROM python:3.11
RUN --mount=type=cache,mode=0777,target=/root/.cache/pip pip install -r requirements.txtAlternatively, you can use the experimental syntax:
# syntax=docker/dockerfile:experimentalNote: The syntax directive must be the first line in the file (before any comments or FROM instructions).
If your Dockerfile runs as a non-root user, you need to specify matching uid/gid values for the cache mount:
# syntax=docker/dockerfile:1
FROM node:18
USER node
# Cache mount with uid/gid matching the 'node' user (typically 1000:1000)
RUN --mount=type=cache,target=/home/node/.npm,uid=1000,gid=1000 npm ciTo find the correct uid/gid for your user, you can run:
docker run --rm node:18 id node
# Output: uid=1000(node) gid=1000(node) groups=1000(node)Cache mounts require BuildKit to be enabled. If you are using Docker Desktop, BuildKit is enabled by default. For Docker Engine, you can enable it by:
Option 1: Set environment variable (per-command)
DOCKER_BUILDKIT=1 docker build -t myapp .Option 2: Configure Docker daemon (permanent)
Add to /etc/docker/daemon.json:
{
"features": {
"buildkit": true
}
}Then restart Docker:
sudo systemctl restart dockerOption 3: Use docker buildx (recommended)
docker buildx build -t myapp .Sometimes corrupted cache data can cause mount failures. Clear the BuildKit cache and try again:
# Clear all BuildKit cache
docker builder prune -a
# Or more selectively, remove only build cache
docker builder prune --filter type=exec.cachemountAfter pruning, rebuild your image:
docker build --no-cache -t myapp .Some package managers (like apt) require exclusive access to their cache. If you see errors related to concurrent access or lock files, use the sharing=locked option:
# syntax=docker/dockerfile:1
FROM ubuntu:22.04
# Use locked sharing for apt cache
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install -y curlThe sharing modes are:
- shared (default): Multiple builds can access simultaneously
- private: Each build gets its own cache instance
- locked: Only one build can access at a time (waits for lock)
If you have multiple Dockerfiles or build jobs that should not share cache, use unique cache IDs:
# In Dockerfile.frontend
RUN --mount=type=cache,id=frontend-npm,target=/root/.npm npm ci
# In Dockerfile.backend
RUN --mount=type=cache,id=backend-npm,target=/root/.npm npm ciFor CI/CD pipelines, you can parameterize the cache ID:
ARG CACHE_ID=default
RUN --mount=type=cache,id=${CACHE_ID}-pip,target=/root/.cache/pip pip install -r requirements.txtBuild with:
docker build --build-arg CACHE_ID=$CI_JOB_ID -t myapp .If you have user namespace remapping enabled (userns-remap in Docker daemon config), cache mounts may fail with permission errors due to uid/gid mapping.
Check if userns-remap is enabled:
docker info | grep -i remapIf enabled, you have a few options:
Option 1: Disable userns-remap for builds (not recommended for production)
Remove or comment out the userns-remap setting in /etc/docker/daemon.json.
Option 2: Map correct uid/gid in your Dockerfile
Account for the remapped uid/gid values in your cache mount configuration.
Option 3: Use docker buildx with a dedicated builder
docker buildx create --name mybuilder --use
docker buildx build -t myapp .As a last resort for debugging or urgent builds, you can disable BuildKit entirely. Note that this will disable all cache mount functionality:
DOCKER_BUILDKIT=0 docker build -t myapp .Your build will proceed without cache mounts, using traditional Docker layer caching. This is useful for determining if BuildKit itself is the issue.
Once your build works, re-enable BuildKit and systematically test which cache mount is causing problems.
### Understanding BuildKit Cache Mounts
Cache mounts in BuildKit work differently from Docker layer caching. While layer caching stores the entire filesystem state after each instruction, cache mounts persist specific directories outside the image layers. This means:
1. Cache mounts are not included in the final image - They only exist during the build process
2. Cache persists across builds - Unlike layer cache which can be invalidated by any change, cache mounts survive instruction changes
3. Cache is local to the builder - The --cache-from and --cache-to options do not include cache mount contents
### CI/CD Considerations
In CI/CD environments like GitHub Actions, BuildKit cache mounts are ephemeral by default. Each build starts with an empty cache. To persist cache mounts between CI runs, you can use:
1. GitHub Actions cache action with buildkit-cache-dance
2. External cache backends like registry or S3 (for layer cache, not mount cache)
3. Self-hosted runners with persistent storage
### Platform-Specific Notes
macOS/Windows Docker Desktop: These platforms use a Linux VM to run containers. File system operations between the host and VM can cause permission issues. Always use mode=0777 or appropriate uid/gid settings.
Linux: Native Docker installations typically have fewer permission issues, but userns-remap and SELinux can still cause problems.
Kubernetes/Podman: BuildKit cache mounts work similarly but may require additional configuration for persistent volumes.
image operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub