挂载不生效
问题场景
挂载卷配置正确,但容器内看不到文件或数据不同步。这是 Docker 运维中常见的问题。
常见原因和解决
1. 路径错误
# ❌ 错误:宿主机路径不存在
docker run -v /not/exists:/app ubuntu
# ✅ 正确
docker run -v /data:/app ubuntu
Docker 有一个”特色”:如果宿主机路径不存在,Docker 会自动创建一个空目录。
2. 权限问题
# 检查宿主机目录权限
ls -la /data
# drwxr-xr-x root root /data
# 容器内用户 (默认 root) 可以读
# 但如果容器以非 root 用户运行
docker run --user 1000:1000 -v /data:/app ubuntu
# Permission denied
解决:
# 方式一:修改宿主机权限
chown -R 1000:1000 /data
# 方式二:使用 uid/gid 映射
docker run --user 1000:1000 -v /data:/app ubuntu:latest
# 方式三:使用主机挂载
docker run --mount type=bind,source=/data,target=/app ubuntu:latest
3. 类型不匹配
# 默认是 bind mount
# 但 volume 需要先创建
docker volume create mydata
docker run -v mydata:/app ubuntu
# bind mount 指定绝对路径
docker run -v /absolute/path:/container/path ubuntu
4. 文件已存在,被隐藏了
# 容器目录 /app 中已有文件
docker run -v /host/data:/app ubuntu
# 结果:/host/data 覆盖了 /app,原文件被隐藏
检查:
# 用 ls -la 查看挂载目录
docker exec ls -la /app
# 查看挂载类型
docker inspect | jq '.[].Mounts'
5. 文件系统限制
# macOS/Windows 的 Docker Desktop
# 需要配置文件共享
# macOS 设置
# Docker Desktop → Preferences → Resources → File Sharing
# 查看挂载是否成功
docker run --rm -v /tmp:/tmp ubuntu ls -la /tmp
6. SELinux/AppArmor
# SELinux 导致挂载不可访问
# 看日志
ausearch -m avc -ts recent
# 解决
docker run -v /data:/app:z ubuntu
# :z 表示重新标记 SELinux 上下文
# :Z 表示使用私有标记
诊断挂载问题
查看容器的挂载信息
# 查看所有挂载
docker inspect | jq '.[].Mounts'
# 输出示例
[
{
"Type": "bind",
"Source": "/home/user/data",
"Destination": "/app/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
]
验证挂载是否生效
# 在宿主机创建文件
echo "hello" > /host-data/test.txt
# 在容器内查看
docker exec cat /app/data/test.txt
# 反过来
docker exec sh -c 'echo "world" > /app/data/test2.txt'
# 在宿主机查看
cat /host-data/test2.txt
Docker Compose 中的挂载
version: '3'
services:
app:
image: nginx:latest
volumes:
# ✅ 推荐方式
- type: bind
source: ./html
target: /usr/share/nginx/html
# ✅ volume 方式
- type: volume
source: app-data
target: /data
# ❌ 容易出错的简写形式
- ./html:/usr/share/nginx/html
volumes:
app-data:
调试脚本
#!/bin/bash
# debug_mount.sh
CONTAINER=$1
MOUNT_POINT=$2
if [ -z "$CONTAINER" ] || [ -z "$MOUNT_POINT" ]; then
echo "Usage: $0 "
exit 1
fi
echo "=== Mount Info ==="
docker inspect $CONTAINER | jq '.[].Mounts'
echo -e "\n=== Check inside container ==="
docker exec $CONTAINER ls -la $MOUNT_POINT
docker exec $CONTAINER mount | grep $MOUNT_POINT
echo -e "\n=== Test write ==="
docker exec $CONTAINER touch $MOUNT_POINT/.test_write && \
echo "✅ Can write" && \
docker exec $CONTAINER rm $MOUNT_POINT/.test_write || \
echo "❌ Cannot write"
面试要点
- 挂载不生效的常见原因按概率排:路径错误 > 权限问题 > 覆盖隐藏 > 文件系统限制
docker inspect的 Mounts 字段是诊断挂载问题的最直接方式- bind mount 和 volume 的行为差异要清楚
- macOS Docker Desktop 的文件共享设置是常见坑
- SELinux 环境下需要使用
:z或:Z标记
面试官常问:bind mount 和 volume 有什么区别?什么时候用哪种?
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容