Docker安装MongoDB并配置主从同步
一、Docker快速安装MongoDB并配置主从同步
| 主机名 | IP |
|---|---|
| mongodb | 192.168.6.14 |
1.1、创建相关目录及授权
1.创建主节点mongodb数据及日志目录并授权
mkdir -p /usr/local/mongodb/mongodb1/data
mkdir -p /usr/local/mongodb/mongodb1/logs
chmod 777 /usr/local/mongodb/mongodb1
2.创建从节点mongodb数据及日志目录并授权
mkdir -p /usr/local/mongodb/mongodb2/data
mkdir -p /usr/local/mongodb/mongodb2/logs
chmod 777 /usr/local/mongodb/mongodb2
3.创建keyFile
keyFile 是一个共享的密钥文件,用于主从节点数据复制时数据主从节点交互安全性,所有复制集成员必须拥有相同的文件内容,并且权限为 600(仅所有者可读)
openssl rand -base64 750 > /usr/local/mongodb/mongodb1/mongodb-keyfile
chmod 600 /usr/local/mongodb/mongodb1/mongodb-keyfile
4.主从节点使用同一个keyfile
cp /usr/local/mongodb/mongodb1/mongodb-keyfile /usr/local/mongodb/mongodb2
chmod 600 /usr/local/mongodb/mongodb2/mongodb-keyfile
5.MongoDB 容器默认以 mongodb 用户运行,需确保该用户有权限访问密钥文件
chown -R 999:999 /usr/local/mongodb/mongodb1/mongodb-keyfile
chown -R 999:999 /usr/local/mongodb/mongodb2/mongodb-keyfile
1.2、下载并运行MongoDB容器
docker pull mongo:latest
# 或使用国内镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mongo:latest
运行mongoDB主节点容器
docker run -d \
--name mongodb1 \
-p 27017:27017 \
-v /usr/local/mongodb/mongodb1/data:/data/db \
-v /usr/local/mongodb/mongodb1/logs:/var/log/mongodb \
-v /etc/localtime:/etc/localtime:ro \
-v /usr/local/mongodb/mongodb1/mongodb-keyfile:/keyfile \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD="123456" \
-e MONGO_BIND_IP=0.0.0.0 \
--restart=always \
--privileged \
mongo:latest \
--replSet rs0 \
--keyFile /keyfile \
--auth
# 参数解释
-v /usr/local/mongodb/mongodb1/mongodb-keyfile:/keyfile # 复制 keyfile 文件(用于副本集认证)
-e MONGO_INITDB_ROOT_USERNAME=root # 初始化 MongoDB 的 root 用户名
-e MONGO_INITDB_ROOT_PASSWORD="123456" # 初始化 MongoDB 的 root 密码
--privileged # 提升容器权限(一般用不到,但这里加上了)
--replSet rs0 # 启用副本集模式,名称为 rs0
--keyFile /keyfile # 启用副本集 keyfile 认证,所有副本集成员用同一个 keyfile
--auth # 开启用户名/密码认证
运行从节点容器
docker run -d \
--name mongodb2 \
-p 37017:27017 \
-v /usr/local/mongodb/mongodb2/data:/data/db \
-v /usr/local/mongodb/mongodb2/logs:/var/log/mongodb \
-v /etc/localtime:/etc/localtime:ro \
-v /usr/local/mongodb/mongodb2/mongodb-keyfile:/keyfile \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD="123456" \
-e MONGO_BIND_IP=0.0.0.0 \
--restart=always \
--privileged \
mongo:latest \
--replSet rs0 \
--keyFile /keyfile \
--auth
1.3、配置主从复制
通过mongosh登录mongodb1(主节点)
docker exec -it mongodb1 mongosh -u root -p '123456' --authenticationDatabase admin

- 切换到admin库
use admin
- 始化复制集
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "192.168.6.14:27017", priority: 1 },
{ _id: 1, host: "192.168.6.14:37017", priority: 0.5 }
]
});

-
priority 参数用于控制节点在选举(election)过程中成为 Primary(主节点) 的优先级,priority=0则仅作为从节点(长用于同步数据); priority: 1, votes: 0 则 无投票权,仅备份
-
检查复制集状态
-
确保所有成员状态为 PRIMARY/SECONDARY(配置均设置0,表示暂停主从复制,实际使用主节点设置1、从节点设置0即可)
rs.status()
rs0 [direct: primary] admin> rs.status()
{
set: 'rs0',
date: ISODate('2025-08-31T14:13:06.424Z'),
myState: 1,
term: Long('1'),
syncSourceHost: '',
syncSourceId: -1,
heartbeatIntervalMillis: Long('2000'),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 2,
writableVotingMembersCount: 2,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
lastCommittedWallTime: ISODate('2025-08-31T14:12:57.783Z'),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
appliedOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
durableOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
writtenOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
lastAppliedWallTime: ISODate('2025-08-31T14:12:57.783Z'),
lastDurableWallTime: ISODate('2025-08-31T14:12:57.783Z'),
lastWrittenWallTime: ISODate('2025-08-31T14:12:57.783Z')
},
lastStableRecoveryTimestamp: Timestamp({ t: 1756649517, i: 1 }),
electionCandidateMetrics: {
lastElectionReason: 'electionTimeout',
lastElectionDate: ISODate('2025-08-31T14:11:17.676Z'),
electionTerm: Long('1'),
lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1756649467, i: 1 }), t: Long('-1') },
lastSeenWrittenOpTimeAtElection: { ts: Timestamp({ t: 1756649467, i: 1 }), t: Long('-1') },
lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1756649467, i: 1 }), t: Long('-1') },
numVotesNeeded: 2,
priorityAtElection: 1,
electionTimeoutMillis: Long('10000'),
numCatchUpOps: Long('0'),
newTermStartDate: ISODate('2025-08-31T14:11:17.723Z'),
wMajorityWriteAvailabilityDate: ISODate('2025-08-31T14:11:18.239Z')
},
members: [
{
_id: 0,
name: '192.168.6.14:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 265,
optime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
optimeDate: ISODate('2025-08-31T14:12:57.000Z'),
optimeWritten: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
optimeWrittenDate: ISODate('2025-08-31T14:12:57.000Z'),
lastAppliedWallTime: ISODate('2025-08-31T14:12:57.783Z'),
lastDurableWallTime: ISODate('2025-08-31T14:12:57.783Z'),
lastWrittenWallTime: ISODate('2025-08-31T14:12:57.783Z'),
syncSourceHost: '',
syncSourceId: -1,
infoMessage: 'Could not find member to sync from',
electionTime: Timestamp({ t: 1756649477, i: 1 }),
electionDate: ISODate('2025-08-31T14:11:17.000Z'),
configVersion: 1,
configTerm: 1,
self: true,
lastHeartbeatMessage: ''
},
{
_id: 1,
name: '192.168.6.14:37017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 119,
optime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
optimeDurable: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
optimeWritten: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
optimeDate: ISODate('2025-08-31T14:12:57.000Z'),
optimeDurableDate: ISODate('2025-08-31T14:12:57.000Z'),
optimeWrittenDate: ISODate('2025-08-31T14:12:57.000Z'),
lastAppliedWallTime: ISODate('2025-08-31T14:12:57.783Z'),
lastDurableWallTime: ISODate('2025-08-31T14:12:57.783Z'),
lastWrittenWallTime: ISODate('2025-08-31T14:12:57.783Z'),
lastHeartbeat: ISODate('2025-08-31T14:13:06.109Z'),
lastHeartbeatRecv: ISODate('2025-08-31T14:13:04.916Z'),
pingMs: Long('0'),
lastHeartbeatMessage: '',
syncSourceHost: '192.168.6.14:27017',
syncSourceId: 0,
infoMessage: '',
configVersion: 1,
configTerm: 1
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1756649577, i: 1 }),
signature: {
hash: Binary.createFromBase64('IYife0nANqmIL4/030rBbkJhLos=', 0),
keyId: Long('7544752054250504197')
}
},
operationTime: Timestamp({ t: 1756649577, i: 1 })
}
rs0 [direct: primary] admin>
1.4、客户端远程连接
上述配置完成后,使用navicat等客户端连接工具远程连接mongodb主库

navicate连接成功后创建一个账户,用于程序连接账号使用(*可选*)

按上述再远程连接从库,最终两个库都连接成功

1.5、验证主从同步
进入mongodb主容器
docker exec -it mongodb1 mongosh -u root -p '123456' --authenticationDatabase admin
# 使用 use 命令切换到目标数据库(若不存在则会自动创建)
use test-databases
# 创建集合
db.createCollection("sys_users")
# 给集合插入数据
db.sys_users.insertOne({ name: "Alice", age: 30 });
进入mongodb从容器查看数据
docker exec -it mongodb2 mongosh -u root -p '123456' --authenticationDatabase admin
rs0 [direct: secondary] test> show dbs;
admin 188.00 KiB
config 240.00 KiB
local 444.00 KiB
test 40.00 KiB
test-databases 40.00 KiB
rs0 [direct: secondary] test> use test-databases
switched to db test-databases
rs0 [direct: secondary] test-databases> show collections
sys_users
rs0 [direct: secondary] test-databases> db.sys_users.find()
[
{ _id: ObjectId('68b45b68332dcf9d7bfe6912'), name: 'Alice', age: 30 }
]
刷新从库后,也生成了测试库、测试集合、并且插入了数据
同理,修改、删除主库的数据库、集合、数据,刷新从库,从库也会同步修改、删除主库的数据库、集合、数据
1.6、常用命令
使用 use 命令切换到目标数据库(若不存在则创建)
use test;
创建集合
db.createCollection("sys_users")
给集合插入数据
db.sys_users.insertOne({ name: "Alice", age: 30,hisdate: 19981201 });
后台创建索引(针对大数量集合,异步原理,防止数据库卡顿)
db.sys_users.createIndex({ hisdate: 1 }, { background: true });
删除索引
db.sys_users.dropIndex("indexName")
查询某个集合索引
db.sys_users.getIndexes();
大数据量集合创建索引执行状态查询
db.currentOp({ "command.createIndexes": "sys_users" });
解释sql,查看查询语句是否使用索引优化
db.sys_users.find(
{ hisdate: { $gte: 20250101, $lte: 20250101 } }
).explain("executionStats");
查询某个集合存储大小(单位:GB)
printjson(db.runCommand({ collstats: 'daq_result_tmp_curve' }).storageSize/(1024*1024*1024))
mongodb资源实时监控
mongostat 是MongoDB自带的实时监控工具,每秒刷新一次关键指标,以下是几个关键指标:
cpu:CPU使用率(用户+系统),低版本可能不支持
res:MongoDB进程的物理内存(Resident Set Size)使用量
flushes:WiredTiger每秒缓存强制刷新次数(高值(如>1/s)可能表示磁盘性能不足或内存不足)
qr|qw:读/写队列长度(高值表示操作积压)
ar:活跃客户端数
docker exec mongodb1 /usr/bin/mongostat --host 192.168.6.14 --port 27017 -u root -p '123456' --authenticationDatabase admin

查询指定库每个集合文档总数和索引总数
# 切换数据库
use acquistion-system;
# 集合总数
var collectionNum=0;
# 查询指定库里集合总数和索引总数
var indexCount = db.getCollectionInfos().reduce((total, coll,collParam) => {
# 获取当前集合的引用
var collection = db.getCollection(coll.name);
# 获取文档数
var documentCount = collection.count();
# 获取索引数
var indexCount = collection.getIndexes().length;
# 输出结果
print("集合名称: " + coll.name + ", 文档数: " + documentCount + ", 索引数: " + indexCount);
collectionNum++;
return total + db.getCollection(coll.name).getIndexes().length;
}, 0);
print("集合总数:" + collectionNum + "; 索引总数: " + indexCount);
浙公网安备 33010602011771号