挂载源的写法歧义
挂载参数一行里同时写着宿主与容器两个路径,写错一边就会出现「文件明明在,容器里是空的」。判别规则很简单:源里带斜杠就当作宿主路径,只有一个裸名称就当作卷名。容易出问题的是相对路径——它按命令执行的当前目录解析,脚本换个目录执行就挂到了别的位置。需要精确表达时用 --mount 显式写明 type、source 与 target。
基本信息
| 判别规则 | 含斜杠视为宿主路径,裸名称视为卷名 |
|---|---|
| 推荐写法 | 绝对路径,或在 shell 里用 $PWD 展开 |
| 更明确的写法 | --mount type=bind,source=绝对路径,target=容器内路径 |
| 核对方式 | docker volume ls 看是否多出一个意料之外的卷 |
典型使用场景
- 脚本里用相对路径挂载:换个工作目录执行,数据就写到了别的地方
- 把目录名误当卷名:容器能启动但数据全在卷里,宿主目录始终是空的
- Windows 路径转义:反斜杠与盘符写法容易解析异常,改用正斜杠更稳
- Compose 与命令行混用:相对路径的解析基准不同,需要统一为绝对路径
- 排查数据到底写在哪:先确认挂载类型,再看是宿主目录还是卷
写法对照示例
写法对照示例
# 裸名称被当作具名卷,数据不在宿主目录里
docker run --rm -v appdata:/data alpine ls /data
# 用绝对路径明确绑定宿主目录
docker run --rm -v /srv/app/data:/data alpine ls /data
# 当前目录展开为字符串再挂载
docker run --rm -v "$PWD/data:/data" alpine ls -l /data
# 用 --mount 表达更不容易歧义
docker run --rm --mount type=bind,source=/srv/app/data,target=/data,readonly alpine ls /data
# 核对是否意外创建了卷
docker volume ls | tail -5常见写法的解释结果
| 写法 | 被解释为 | 主要风险 |
|---|---|---|
| ./data:/data | 宿主相对路径(按当前目录解析) | 执行目录变化后挂到不一致的位置 |
| data:/data | 具名卷 data | 数据进卷,宿主目录里看不到内容 |
| /srv/data:/data | 宿主绝对路径 | 路径不存在时会新建目录或直接失败 |
| Windows 盘符路径 | 宿主路径(需正确转义) | 反斜杠解析异常,建议改用正斜杠 |
拿不准时先跑一次 docker volume ls:如果多出一个不该有的卷名,说明挂载源被当成卷解析了。
绑定挂载不会把镜像目录里的原有内容复制进去,空目录挂上去就是空的,这一点与具名卷的初始化行为不同。