挂载不生效

挂载不生效

问题场景

挂载卷配置正确,但容器内看不到文件或数据不同步。这是 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"

面试要点

  1. 挂载不生效的常见原因按概率排:路径错误 > 权限问题 > 覆盖隐藏 > 文件系统限制
  2. docker inspect 的 Mounts 字段是诊断挂载问题的最直接方式
  3. bind mount 和 volume 的行为差异要清楚
  4. macOS Docker Desktop 的文件共享设置是常见坑
  5. SELinux 环境下需要使用 :z:Z 标记

面试官常问:bind mount 和 volume 有什么区别?什么时候用哪种?

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容