TL;DR
- 场景 :用 Docker 在本机快速起一个 MongoDB 7 副本集,带内网鉴权与管理员账号。
- 结论 :生成
keyfile→docker compose up -d→ 一次性容器自动rs.initiate + createUser;明确开启 --auth。 - 产出 :
docker-compose.yml、幂等初始化脚本、连接URI与校验清单。

集群搭建1-容器版
最小可运行示例MRE
shell
# 1) 生成副本集 keyfile(权限必须 600)
openssl rand -base64 756 > mongo-keyfile && chmod 600 mongo-keyfile
# 2) 启动
docker compose up -d
# 3) 校验:查看 primary 与成员状态
docker exec -it mongo1 mongosh --eval "rs.status().members.map(m=>({host:m.name,state:m.stateStr}))"
# 4) 用管理员连接(容器内DNS)
docker exec -it mongo1 mongosh "mongodb://admin:admin123@mongo1:27017/?replicaSet=rs0&authSource=admin"
版本信息
| 组件 | 已验证 | 备注 |
|---|---|---|
| MongoDB | 7.0.x | 镜像 mongo:7.0 |
| Docker | 24+ | 本地/服务器均可 |
| Compose | v2 | docker compose 子命令 |
| OS | Ubuntu 22.04/24.04、macOS | 任一即可 |
准备 keyfile
集群内鉴权必须需要有 keyfile:
shell
openssl rand -base64 756 > mongo-keyfile
chmod 600 mongo-keyfile
注意keyfile的内容不要泄露了,我这里是本地测试,后续就不用了:

docker-compose
准备 docker-compose 文件如下所示:
yaml
version: "3.9"
services:
mongo1:
image: mongo:7.0
container_name: mongo1
hostname: mongo1
ports:
- "27017:27017"
volumes:
- ./mongo1-data:/data/db
- ./mongo-keyfile:/etc/mongo-keyfile:ro
command: ["mongod","--replSet","rs0","--bind_ip_all", "--keyFile", "/etc/mongo-keyfile"]
networks: [mongo-net]
mongo2:
image: mongo:7.0
container_name: mongo2
hostname: mongo2
volumes:
- ./mongo2-data:/data/db
- ./mongo-keyfile:/etc/mongo-keyfile:ro
command: ["mongod","--replSet","rs0","--bind_ip_all", "--keyFile", "/etc/mongo-keyfile"]
networks: [mongo-net]
mongo3:
image: mongo:7.0
container_name: mongo3
hostname: mongo3
volumes:
- ./mongo3-data:/data/db
- ./mongo-keyfile:/etc/mongo-keyfile:ro
command: ["mongod","--replSet","rs0","--bind_ip_all", "--keyFile", "/etc/mongo-keyfile"]
networks: [mongo-net]
# 一次性初始化副本集 + 创建管理员账号
init-rs:
image: mongo:7.0
container_name: init-rs
depends_on: [mongo1, mongo2, mongo3]
networks: [mongo-net]
entrypoint: [ "bash", "-lc" ]
command: |
'
# 等待 primary 可用
until mongosh --host mongo1 --quiet --eval "db.adminCommand({ping:1})" >/dev/null 2>&1; do
echo "waiting mongo1..."
sleep 2
done
mongosh --host mongo1 << "EOF"
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "mongo1:27017", priority: 2 },
{ _id: 1, host: "mongo2:27017", priority: 1 },
{ _id: 2, host: "mongo3:27017", priority: 1 }
]
})
// 等待选主
function waitPrimary() {
while (true) {
s = rs.status();
if (s.members && s.members.some(m => m.stateStr === "PRIMARY")) { break; }
sleep(1000);
}
}
waitPrimary();
// 创建 root 管理员
use admin
db.createUser({
user: "admin",
pwd: "admin123",
roles: [ { role: "root", db: "admin" } ]
})
print("ReplicaSet initialized and admin user created.")
EOF
'
restart: "no"
networks:
mongo-net:
driver: bridge
启动服务
我们启动服务:

容器外(本机)直连 primary(开发调试):
shell
mongodb://admin:admin123@localhost:27017/?replicaSet=rs0&authSource=admin
容器内/同网络(更推荐,具备副本集感知):
shell
mongodb://admin:admin123@mongo1:27017,mongo2:27017,mongo3:27017/?replicaSet=rs0&authSource=admin
我们输入数据库的地址进行连接:
shell
mongodb://admin:admin123@localhost:27017/?directConnection=true&authSource=admin
可以看到如下情况:

快速检查清单
shell
# 1) 成员与角色
docker exec -it mongo1 mongosh --eval 'rs.status().members.map(m=>m.name+" -> "+m.stateStr)'
# 2) 权限有效(应返回1)
docker exec -it mongo1 mongosh "mongodb://admin:admin123@mongo1:27017/admin?replicaSet=rs0" --eval 'db.runCommand({ping:1}).ok'
# 3) 写入与读回
docker exec -it mongo1 mongosh "mongodb://admin:admin123@mongo1:27017/test?replicaSet=rs0" --eval 'db.t.insertOne({ok:1}); printjson(db.t.findOne())'
回滚/销毁剧本(谨慎,会删数据)
shell
# 停止
docker compose down
# 清理数据目录(危险)
sudo rm -rf mongo1-data mongo2-data mongo3-data
rm -f mongo-keyfile
常见报错
| 症状 | 根因 | 快排 |
|---|---|---|
| BadValue: permissions on keyfile are too open | mongo-keyfile 非 600 | chmod 600 mongo-keyfile,确保挂载为 :ro |
| NotYetInitialized | 连接在 rs.initiate 前 | 等待 init-rs 完成或手动执行 rs.initiate() |
| Authentication failed | 密码特殊符号/错库 | 在 URI 中对特殊字符转义;确认 authSource=admin |
| ReplicaSetNoPrimary | 还未选主或优先级配置不当 | 再等几秒;检查 priority 与容器 DNS 可达性 |
FAQ
- 为啥只映射 27017? 开发机只需连主即可;副本发现靠 replicaSet 参数自动解析。
- keyfile 会泄露吗? 生产必须妥善保管并限制权限;本文示例为本地环境。
- 如何固定某一台为 Primary? 调整 priority,并确保网络可达。
- 如何扩容到 5 节点? 新增服务并 rs.add,或在 init 脚本里扩展 members。
- 如何接入 Spring Boot? 使用 spring.data.mongodb.uri,保持 replicaSet 与 authSource 参数一致。
其他系列
🚀 AI篇持续更新中(长期更新)
AI炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究 ,持续打造实用AI工具指南!
AI-调查研究-108-具身智能 机器人模型训练全流程详解:从预训练到强化学习与人类反馈
🔗 AI模块直达链接
💻 Java篇持续更新中(长期更新)
Java-154 深入浅出 MongoDB 用Java访问 MongoDB 数据库 从环境搭建到CRUD完整示例
MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务正在更新!深入浅出助你打牢基础!
🔗 Java模块直达链接
📊 大数据板块已完成多项干货更新(300篇):
包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!
大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解
🔗 大数据模块直达链接