必须同时设置mongo_initdb_root_username和mongo_initdb_root_password,否则官方镜像不启用鉴权;二者均非空时,docker-entrypoint.sh才创建root用户并开启--auth模式,且仅在/data/db为空时首次启动生效。

必须同时设置 MONGO_INITDB_ROOT_USERNAME 和 MONGO_INITDB_ROOT_PASSWORD,否则 MongoDB 官方镜像不会启用鉴权,连接时也不会报错——你只会以为“它没生效”,其实是根本没触发初始化逻辑。
为什么只设用户名或只设密码都不行
官方镜像的 docker-entrypoint.sh 脚本里有明确判断:只有两个变量都非空,才会执行 db.createUser(...) 并自动开启 --auth 模式。漏掉任意一个,容器就退化为无鉴权模式,use admin; db.auth(...) 会失败,且 listDatabases 等命令能直接执行——这不是“连上了”,是“根本没锁门”。
-
MONGO_INITDB_ROOT_USERNAME和MONGO_INITDB_ROOT_PASSWORD是硬编码变量名,不能改成ADMIN_USER或ROOT_PWD - 它们只在容器首次启动、且
/data/db目录为空(或 volume 第一次挂载)时生效 - 一旦初始化完成,再改环境变量重启容器,对已有数据库完全无效
docker-compose.yml 中的典型写法
注意 YAML 缩进和冒号后空格——这是最容易出错的地方。下面这段配置能正确触发鉴权初始化:
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
services:
mongodb:
image: mongo:6.0
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: myS3cureP@ss
TZ: Asia/Shanghai
volumes:
- mongo_data:/data/db
- ./init.js:/docker-entrypoint-initdb.d/init.js:ro
ports:
- "27017:27017"
volumes:
mongo_data:
- 确保
volumes下的mongo_data是全新 volume,或已用docker-compose down -v清空过 -
init.js是可选的额外初始化脚本,它会在 root 用户创建之后执行,可用于建业务库、普通用户等 - 不要在 environment 里加引号包裹密码(如
"myS3cureP@ss"),YAML 解析可能吃掉特殊字符
验证鉴权是否真正生效
别只看容器日志有没有“initializing”字样。真正有效的验证方式是连上去试操作:
- 用
docker exec -it mongodb mongo -u admin -p myS3cureP@ss --authenticationDatabase admin进入 shell - 执行
use admin; db.runCommand({ listDatabases: 1 })—— 应该成功返回数据库列表 - 切换到非 admin 库,比如
use test,再执行db.test.insertOne({x:1})—— 应该报错"not authorized on test to execute command" - 如果
show dbs能直接列出所有库,说明鉴权根本没开
常见踩坑点:挂载了旧 volume 却反复修改环境变量
这是最常被忽略的环节。当你第一次启动容器后,/data/db 已被初始化并持久化;后续无论你怎么改 MONGO_INITDB_ROOT_PASSWORD,镜像都不会重新跑初始化流程——它只检查目录是否为空。
- 想重试?必须先
docker-compose down -v,再docker volume ls确认mongo_data已消失 - 如果用的是 bind mount(如
./data:/data/db),要手动rm -rf ./data - 某些 CI/CD 流程中误复用 volume,会导致本地测试通过、部署失败
初始化逻辑只跑一次,且只看数据目录状态,不看环境变量历史——这点比大多数人的直觉更“固执”。










