✦ For everyone, free.

Practical knowledge for real and everyday life

Home

16.3.1.4 Wrong Mount Target

A focused guide to Wrong Mount Target, connecting core concepts with practical Docker and container operations.

A wrong mount target is a volume or bind mount specified at a path that does not actually match where the application expects to find its data, producing a container that runs without error, appears to have a volume correctly attached, and yet behaves as though no persistence exists at all, since the application is reading and writing an entirely different, unmounted path than the one Docker is actually managing.

Why this fails silently

Mounting a volume at the wrong path produces no error of any kind; Docker faithfully creates the mount exactly where requested, and the container starts and runs normally. The only symptom is that data written by the application never appears in the mounted volume, and a container replacement causes that data to disappear, exactly as if no volume had ever been configured at all:

docker run -d -v pgdata:/var/lib/postgres/data postgres
docker exec my-db psql -U postgres -c "SHOW data_directory;"
/var/lib/postgresql/data

The volume mount in this example targets /var/lib/postgres/data (missing the ql in postgresql), a path that does not match where PostgreSQL actually stores its data (/var/lib/postgresql/data), which means the volume is mounted at an empty, irrelevant location while the database continues writing to the container's own disposable writable layer instead.

Verifying the application's actual expected path

Before configuring any mount, confirming the application's actual, correct data directory directly, rather than assuming a path based on memory, documentation that may be for a different version, or a copied example, avoids this mismatch at the source:

docker run --rm postgres cat /usr/share/doc/postgresql-*/README.Debian 2>/dev/null | grep -i "data directory"
docker exec my-db env | grep -i data

For official, well-documented images, checking the image's own documentation or its default configuration directly is more reliable than relying on a general assumption, particularly since the exact expected path can differ between major versions of the same software or between different official images for ostensibly the same database engine.

Detecting a wrong mount target after the fact

A volume that appears correctly attached through docker inspect but contains no actual application data, despite the application clearly having been running and presumably writing something, is the clearest symptom of a mount target mismatch:

docker run --rm -v pgdata:/check alpine ls -la /check
total 8
drwxr-xr-x 2 root root 4096 Jun 1 12:00 .
drwxr-xr-x 3 root root 4096 Jun 1 12:00 ..

An empty or unexpectedly sparse volume, despite the application clearly having processed data during the container's runtime, strongly suggests the mount target does not actually correspond to wherever the application is genuinely writing.

Comparing the mount target against the actual write location

Directly confirming where the running container's process is genuinely writing, compared against where the volume is mounted, resolves any ambiguity definitively:

docker exec my-db lsof -p 1 | grep -i data
docker exec my-db strace -f -e trace=open,openat -p 1 2>&1 | grep -i write

For applications without a convenient configuration command to query their data path directly, observing actual file operations through tools like lsof or strace against the running process provides direct, conclusive evidence of exactly which paths it is genuinely interacting with, removing any need to rely on assumption or documentation alone.

Multi-stage and Compose override path mismatches

A wrong mount target can also arise from inconsistency between a base Compose file and an override file, where one file's path no longer matches the other after one was updated without the corresponding change being made to the other:

services:
  db:
    volumes:
      - pgdata:/var/lib/postgresql/data
services:
  db:
    image: postgres:16
    environment:
      - PGDATA=/var/lib/postgresql/data/pgdata

If a PGDATA environment variable override shifts the application's actual data directory to a subdirectory of the originally mounted path, the volume mount itself, still targeting the parent directory, would actually still work correctly here since the subdirectory is within the mounted path; but the inverse case, where the override moves the data path entirely outside the originally mounted directory, would reproduce the same silent mismatch problem, which is worth checking explicitly whenever an environment variable affecting a data path changes without a corresponding review of the volume mount target.

The same problem with bind mounts

Bind mounts are equally susceptible to this mismatch, and because a bind mount source path appears explicitly in the configuration, a typo or incorrect assumption about the application's expected destination path produces the identical silent failure mode:

docker run -v /srv/app-data:/app/dat my-api

A single missing letter in the destination path (/app/dat instead of the application's actual expected /app/data) produces a mount that is technically present and correctly bound to the host directory, but at a path the application never reads from or writes to at all.

Establishing a verification habit for any new mount configuration

Given how silent this failure mode is, deliberately verifying a new or changed mount configuration immediately after deploying it, rather than assuming correctness based on the configuration looking reasonable, catches this class of mistake before it has a chance to cause a real data loss incident down the line:

docker exec my-api sh -c "echo verify-$(date +%s) > /app/data/verify.txt"
docker run --rm -v app-data:/check alpine cat /check/verify.txt

Writing a known, identifiable test value through the application's actual expected path, then confirming that exact value appears within the mounted volume when inspected independently, provides direct, conclusive proof the mount target is correctly aligned with where the application actually writes.

Common mistakes

  • Assuming a mount target path based on memory, an outdated example, or general assumption rather than confirming the application's actual expected data directory directly.
  • Not noticing a typo in a mount target path, since Docker creates the mount successfully and produces no error regardless of whether the path actually matches anything the application uses.
  • Reviewing only the volume's attachment in docker inspect as confirmation of correct persistence, without ever checking whether the volume actually contains the expected data.
  • Updating an environment variable that shifts an application's effective data path without revisiting whether the existing volume mount target still aligns with the new path.
  • Deploying a new or changed mount configuration without verifying it end to end through an explicit write-and-check test before trusting it for real, valuable data.

A wrong mount target is one of the more dangerous Docker misconfigurations precisely because it produces no error and no immediately visible symptom, only a quiet, complete absence of the persistence an operator believes is in place, and the only reliable defense is directly verifying, through an explicit write-and-read test, that the mounted path and the application's actual data path are genuinely the same location.