-v packs everything into one colon-separated string. --mount spells each part out as key=value. Both create the same mounts; --mount is easier to read and rejects mistakes that -v accepts.
text
--mount type=volume,source=build-cache,target=/cache,readonly
└── kind ──┘ └──── on host ──┘ └─ in container ┘ └ option ┘Keys
| Key | Aliases | Meaning |
|---|---|---|
type | volume (default), bind or tmpfs | |
source | src | Volume name, or absolute host path for bind. Omit for an anonymous volume |
target | dst, destination | Path inside the container (required) |
readonly | ro | Mount read-only |
The three mount types
text
container
┌─────────────────────────────┐
│ /cache /assets /tmp/build
└───┬────────────┬──────────┬──┘
▼ ▼ ▼
volume bind tmpfs
managed by any host memory only,
Docker path gone on stop| Type | Data lives in | Use for |
|---|---|---|
volume | /var/lib/docker/volumes/NAME/_data | Application data: databases, uploads, caches |
bind | A host path you choose | Source code, config files, sharing files with host tools |
tmpfs | Memory | Scratch files and secrets that must never reach disk |
-v and --mount side by side
-v | --mount |
|---|---|
-v build-cache:/cache | --mount type=volume,source=build-cache,target=/cache |
-v /home/learner/project/assets:/assets:ro | --mount type=bind,source=/home/learner/project/assets,target=/assets,readonly |
--tmpfs /tmp/build | --mount type=tmpfs,target=/tmp/build |
A run with all three:
sh
docker run -d --name ci \
--mount type=volume,source=build-cache,target=/cache \
--mount type=bind,source=$HOME/project/assets,target=/assets,readonly \
--mount type=tmpfs,target=/tmp/build \
alpine:3.20 sleep infinityThe difference that matters: a missing bind source
text
$ docker run -d --mount type=bind,source=$HOME/assets,target=/assets alpine:3.20 sleep infinity
docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /home/learner/assets.With -v $HOME/assets:/assets, Docker creates an empty ~/assets owned by root and starts the container. The application then runs against an empty directory instead of failing. --mount stops at the typo.
Read the mounts back
sh
docker inspect --format '{{range .Mounts}}{{.Type}} {{.Source}} -> {{.Destination}} rw={{.RW}}{{println}}{{end}}' citext
volume /var/lib/docker/volumes/build-cache/_data -> /cache rw=true
bind /home/learner/project/assets -> /assets rw=false
tmpfs -> /tmp/build rw=trueWriting to a read-only mount fails inside the container:
text
$ docker exec ci touch /assets/x
touch: cannot touch '/assets/x': Read-only file system