挂载 /data/db 是唯一有效方式:GridFS 无独立存储路径,所有数据均由 WiredTiger 写入 /data/db 下的 .wt 文件;额外挂载如 /gridfs 无效,且宿主机目录须 chown 999:999 并确保 mongod.conf 中 dbPath 严格设为 /data/db。

挂载 /data/db 是唯一有效方式
GridFS 没有独立存储路径,它只是驱动层对 fs.files 和 fs.chunks 集合的操作封装,所有数据最终由 WiredTiger 写入 /data/db 下的 *.wt 文件。试图额外挂载 /gridfs 或 /data/gridfs 完全无效——mongod 不识别这些路径,也不会把文件写进去。
常见错误现象包括:容器启动后日志报 Permission denied 或 Encountered unclean shutdown, and unable to lock database directory,实际是挂载失败导致 WiredTiger 初始化中断。
- 必须使用
-v /host/path:/data/db,不能映射到其他路径 - 宿主机目录需提前创建并执行
chown 999:999 /host/path(官方镜像以 UID 999 运行) - 若用命名卷(
docker volume create mongo-data),无需手动 chown,但升级镜像时需导出/导入数据
mongod.conf 中的 dbPath 必须严格匹配挂载目标
如果你挂载的是 /mnt/mongo-data:/data/db,但配置文件里写了 storage: dbPath: /data/mongo/data,WiredTiger 就会去初始化一个根本没挂载的空目录,结果要么失败,要么数据写进容器临时文件系统、重启即丢。
正确做法是保持配置简洁:
- 不提供配置文件,靠默认行为(官方镜像默认
dbPath就是/data/db) - 若必须用配置文件,确保其中
dbPath: /data/db,且不能加任何前缀或变量 - 不要在配置里改
storage.engine或wiredTigerCacheSizeGB后不验证——大文件场景下,--wiredTigerCacheSizeGB设太高反而挤占系统内存,建议设为物理内存的 50%~60%
GridFS 大文件写入后,如何确认已持久化?
不能只看容器是否运行,也不能只查 fs.files 是否有记录——因为集合元数据可能已写入,但 fs.chunks 的块数据还在 journal 缓冲区里没刷盘。真正可靠的验证点是宿主机挂载目录中是否存在对应 .wt 文件,并且大小随上传增长。
- 上传一个 >10MB 的测试文件(如视频),再执行
docker exec -it mongo-container ls -lh /data/db/*.wt - 对比宿主机上
ls -lh /mnt/mongo-data/*.wt,两者应基本一致(允许几秒延迟) - 停掉容器、删掉容器、重新
docker run -v /mnt/mongo-data:/data/db mongo:6.0,再连上去查db.fs.files.countDocuments(),数量应不变
Docker Compose 下容易忽略的权限陷阱
很多人以为 volumes: 块里写好路径就完事了,其实 compose 不会自动创建宿主机目录,更不会帮你 chown。容器启动失败时,错误日志往往只显示 Failed to create directory /data/db,根本不会提示“你少 chown”。
最稳妥的做法是把权限准备步骤写进部署流程,而不是依赖容器内脚本:
- 部署前手动执行:
mkdir -p /mnt/mongo-data && chown 999:999 /mnt/mongo-data - 避免用
initContainer或自定义 entrypoint 改权限——WiredTiger 对目录权限极其敏感,chmod 777反而会导致启动失败 - 如果用 NFS 或云盘挂载,确认其支持
chown和 POSIX 权限;某些对象存储网关挂载不满足要求,会静默降级为只读
openUploadStream,而取决于 /data/db 是否真实、可写、权限对得上——这三个条件缺一不可,且最后一个最容易被跳过检查。


















