# 通过docker-compose快速搭建mongodb副本集

文章目录

前言

mongoDB 提供的副本集是将数据同步至多个节点,提供了数据冗余备份和节点故障的情况下可以自动转移的高可用特性,架构图如下:

有时候需要要在本地搭建一套 mongoDB 副本集环境来做测试,如果用虚拟机的话还是比较麻烦的,这里记录下如何用 docker-compose 快速搭建 mongoDB 副本集。

构建镜像

  1. 准备秘钥用于节点之间的认证
openssl rand -base64 756 > auth.key
  1. 编写 Dockerfile

调整 mongo 官方提供的镜像,像里面添加秘钥文件

FROM mongo:3.4.10
#将秘钥文件复制到镜像中
COPY auth.key /app/auth.key
RUN chown -R mongodb:mongodb /app/auth.key
#设置秘钥文件权限,这一步非常关键
RUN chmod 600 /app/auth.key
  1. 构建镜像
docker build -t mongo-replset .
  1. 编写 docker-compose

开启三个容器,组成一主两从的副本集集群,另外再开启一个容器监听和初始化副本集,这里我的实现方式并不优雅,就是一直重试直到前面三个 mongod 进程启动完成(官方有个解决方案来检测依赖服务的启动,不过有点麻烦这里就略过了),启动完成之后执行副本集初始化命令:mongo mongodb://root:123@mongo-1:27011/admin --eval 'rs.initiate({ _id: "rs", members: [{_id:1,host:"mongo-1:27011"},{_id:2,host:"mongo-2:27012"},{_id:3,host:"mongo-3:27013"}]})'

version: "3.1"
services:
mongo-1:
image: mongo-replset
hostname: mongo-1
restart: always
ports:
- 27011:27011
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 123
command:
- --port
- "27011"
- --replSet
- rs
- --keyFile
- /app/auth.key
mongo-2:
image: mongo-replset
hostname: mongo-2
restart: always
ports:
- 27012:27012
command:
- --port
- "27012"
- --replSet
- rs
- --keyFile
- /app/auth.key
mongo-3:
image: mongo-replset
hostname: mongo-3
restart: always
ports:
- 27013:27013
command:
- --port
- "27013"
- --replSet
- rs
- --keyFile
- /app/auth.key
mongo-init:
image: mongo:3.4.10
depends_on:
- mongo-1
- mongo-2
- mongo-3
restart: on-failure:5
command:
- mongo
- mongodb://root:123@mongo-1:27011/admin
- --eval
- 'rs.initiate({ _id: "rs", members: [{_id:1,host:"mongo-1:27011"},{_id:2,host:"mongo-2:27012"},{_id:3,host:"mongo-3:27013"}]})'
  1. 运行
docker-compose up -d
Creating mongo-replica_mongo-1_1 ... done
Creating mongo-replica_mongo-3_1 ... done
Creating mongo-replica_mongo-2_1 ... done
Creating mongo-replica_mongo-init_1 ... done
  1. 查看副本集状态
docker-compose exec mongo-1 mongo mongodb://root:123@mongo-1:27011/admin --eval 'rs.status()'
MongoDB shell version v3.4.10
connecting to: mongodb://root:123@mongo-1:27011/admin
MongoDB server version: 3.4.10
{
"set" : "rs",
"date" : ISODate("2020-03-10T07:01:59.764Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1583823710, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1583823710, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1583823710, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 1,
"name" : "mongo-1:27011",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 263,
"optime" : {
"ts" : Timestamp(1583823710, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-03-10T07:01:50Z"),
"electionTime" : Timestamp(1583823469, 1),
"electionDate" : ISODate("2020-03-10T06:57:49Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 2,
"name" : "mongo-2:27012",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 261,
"optime" : {
"ts" : Timestamp(1583823710, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1583823710, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-03-10T07:01:50Z"),
"optimeDurableDate" : ISODate("2020-03-10T07:01:50Z"),
"lastHeartbeat" : ISODate("2020-03-10T07:01:59.120Z"),
"lastHeartbeatRecv" : ISODate("2020-03-10T07:01:58.109Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "mongo-1:27011",
"configVersion" : 1
},
{
"_id" : 3,
"name" : "mongo-3:27013",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 261,
"optime" : {
"ts" : Timestamp(1583823710, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1583823710, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-03-10T07:01:50Z"),
"optimeDurableDate" : ISODate("2020-03-10T07:01:50Z"),
"lastHeartbeat" : ISODate("2020-03-10T07:01:59.120Z"),
"lastHeartbeatRecv" : ISODate("2020-03-10T07:01:58.103Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "mongo-1:27011",
"configVersion" : 1
}
],
"ok" : 1
}

后记

使用 docker-compose 搭建的 mongodb 副本集就完成了,以后可以基于此快速搭建一套 mongodb 副本集环境进行测试。


More Posts

# docker清理

1 min read

docker 在使用过程中,可能会产生很多冗余无用的数据,这些数据会占用大量硬盘空间,这里记录下如何清理 docker。

阅读

# 设计一种无状态的验证码

6 min read

通常验证码都是通过session来实现,在服务端生成一个随机字符串作为验证码,将该字符串存到session中,然后将验证码图片渲染到前端,前端提交之后通过session中存放的正确验证码进行对比从而验证输入的正确性。

阅读

评论区