DockerCompose 搭建 MongoDB 副本集

本文介绍如何在 windows 环境中通过 docker-compose 创建 MongoDB 副本集。

生成 keyFile

  • MongoDB使用keyfile认证,副本集中的每个mongod实例使用keyfile内容作为认证其他成员的共享密码。mongod实例只有拥有正确的keyfile才可以加入副本集。
  • keyFile的内容必须是6到1024个字符的长度,且副本集所有成员的keyFile内容必须相同。
  • 有一点要注意是的:在UNIX系统中,keyFile必须没有组权限或完全权限(也就是权限要设置成X00的形式)。Windows系统中,keyFile权限没有被检查。
  • 可以使用任意方法生成keyFile。例如,如下操作使用 openssl 生成复杂的随机的1024个字符串。
1
2
cd key
openssl rand -base64 756 > mongodb.key

详细的docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# yaml 配置

version: "3.9"

services:
# 管理 redis 的可视化工具
redis-commander:
image: rediscommander/redis-commander:latest
container_name: redis-commander
restart: always
ports:
- 8081:8081
environment:
- REDIS_HOSTS=redis
networks:
- redis-net

# iepc mongodb 服务
# 主节点
mongodb27018:
hostname: mongodb27018
container_name: mongodb27018
image: mongo:latest
expose:
- 27018
ports:
- 27018:27017
restart: always
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=yourPassword
command: mongod --bind_ip_all --replSet rs_share --keyFile /mongodb.key
volumes:
- D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc\rs1\data:/data/db
- D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc\rs1\configdb:/data/configdb
- D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc\rs1\mongodb.key:/mongodb.key
networks:
- MongoDB-net
entrypoint:
- bash
- -c
- |
chmod 400 /mongodb.key
chown 999:999 /mongodb.key
exec docker-entrypoint.sh $$@

# 副节点
mongodb27019:
hostname: mongodb27019
container_name: mongodb27019
image: mongo:latest
expose:
- 27019
ports:
- 27019:27017
restart: always
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=yourPassword
command: mongod --bind_ip_all --replSet rs_share --keyFile /mongodb.key
volumes:
- D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc\rs2\data:/data/db
- D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc\rs2\configdb:/data/configdb
- D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc\rs1\mongodb.key:/mongodb.key
networks:
- MongoDB-net
entrypoint:
- bash
- -c
- |
chmod 400 /mongodb.key
chown 999:999 /mongodb.key
exec docker-entrypoint.sh $$@
depends_on:
- mongodb27018

mongodb27020:
# Host name = Container name
hostname: mongodb27020
container_name: mongodb27020
image: mongo:latest
expose:
- 27020
ports:
- 27020:27017
restart: always
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=yourPassword
command: mongod --bind_ip_all --replSet rs_share --keyFile /mongodb.key
volumes:
- D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc\rs3\data:/data/db
- D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc\rs3\configdb:/data/configdb
- D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc\rs1\mongodb.key:/mongodb.key
networks:
- MongoDB-net
entrypoint:
- bash
- -c
- |
chmod 400 /mongodb.key
chown 999:999 /mongodb.key
exec docker-entrypoint.sh $$@
depends_on:
- mongodb27019

networks:
# 设置 mongodb-net 为 bridge 模式,参考:https://zhuanlan.zhihu.com/p/212772001
mongodb-net:
driver: bridge

创建挂载目录

1
2
z D:\Verysync\SoftwareSettings\Docker\MongoDB\iepc
mkdir -p rs1/data,rs1/configdb,rs2/data,rs2/configdb,rs3/data,rs1/configdb

其中 z 命令是安装了 z.lua 获取,mkdir 命令安装 busybox 获取

复制 mongodb.key 到配置中的指定位置。

部署容器

进入到 docker-compose.yml 目录,终端中执行 docker compose up -d 或者 docker-compose up -d 来部署容器。

image-20230416124522790

错误处理

错误 1:error during connect: in the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect

docker desktop 没有启动,先启动,再运行

配置副本集

进入 mongodb

1
2
3
4
5
6
#进入 mongodb27018 的容器内
docker exec -it mongodb27018 bash

# 进入mongo shell
# MongoDB 之前使用 mongo,之后使用 mongosh
mongosh -u root -p yourPassword

The mongo shell is removed from MongoDB 6.0. The replacement is mongosh.

初始化副本集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 切换到 admin
use admin
# 进行授权认证
# 返回 { ok: 1 } 表示成功
db.auth("root","yourPassword")
# 定义配置文件
# 配置中的 host 必须是本机实际的 ip,不能是 127.0.0.1,否则局域网内无法访问
# 如果要通过域名访问,则必须是域名
rsconf = {
_id: "rs_share",
members: [
{
_id: 0,
host: "192.168.3.240:27018"
},
{
_id: 1,
host: "192.168.3.240:27019"
},
{
_id: 2,
host: "192.168.3.240:27020"
}
]
}

# 初始化副本集
rs.initiate(rsconf)

若是只有一个节点,则只需要执行:rs.initiate()

当出现如下提示时,说明成功了:

1
2
{ "ok" : 1 }
rs_auth:SECONDARY>

单主机模式部署 3副本集 添加节点必须使用宿主机IP+PORT,使用容器内部IP的情况下代码层面连接到 mongodb-cluster 集群,获取到的集群地址信息为 docker 容器内部 IP,若业务代码没有部署在 mongodb 主机则无法访问

修改副本集配置

若是更换了主机 IP,则需要重新修改副本集中的 host,可以采用下列方式修改:

先按 进入 mongodb 登陆到 mongodb,然后使用

1
rs.status().members.find(x=>x.stateStr === 'PRIMARY')

来查找主节点。

若当前实例不是主节点,则退出重新登陆到主节点中

修改配置

1
2
3
4
5
6
7
8
9
10
11
# 切换到 admin
use admin
# 进行授权认证
# 返回 { ok: 1 } 表示成功
db.auth("root","yourPassword")
# 获取当前的副本集配置
config = rs.conf();
# 修改配置
config.members[0].host = "newhost:27017";
# 应用新的配置
rs.reconfig(config);

你的 MongoDB 版本是 4.2 或更高版本,可以使用 rs.reconfig() 方法的 force 参数来强制应用新的配置,即使新的配置和当前的配置不兼容:

1
2
# 这个操作可能会导致数据丢失,谨慎使用
rs.reconfig(config, { force: true });

rs.reconfig() 方法会导致副本集的所有成员(包括主节点)重新启动

参考

MongoDB 3 副本集群(Docker-compose部署)(单机模式)