在工作中存在使用单节点mongodb的情况,而在使用mongodb中避免不了使用事务的场景,在mongodb中事务的使用需在使用副本集的情况下才能运用。
本文机器使用docker+mongo4.0以上版本
设:
宿主机ip 192.168.100.10
docker容器ip:172.10.10.10
1. 快速上手
使用docker-compose部署,以下是docker-compose.yaml配置
version: "3"
services:
main:
image: mongo:4.4
container_name: mongo
ports:
- 47017:27017
# 可选的数据挂载
volumes:
- /mongo/conf:/conf
- /mongo/mongosh-1.8.0-linux-x64/bin:/root/bin
- /mongo/data:/data/db
restart: always
entrypoint: [ "/usr/bin/mongod", "-f", "/conf/mongo.conf"]
注意:/mongo/mongosh-1.8.0-linux-x64/bin 这是自己下载的mongosh,下载链接如下
wget https://downloads.mongodb.com/compass/mongosh-1.8.0-linux-x64.tgz
如下是指定的配置文件信息
dbpath=/data/db
bind_ip=0.0.0.0
port=27017
replSet=rs0
然后就可以用docker-compose -f的方式启动mongod容器,在启动后基于如下命令进入容器
docker exec -it mongo bash
# 进入容器后
cd /root/bin
# 初始化mongo副本集
mongosh
mongo> rs.initiate({
_id: "rs0",
version: 1,
members: [
{ _id: 0, host : "192.168.100.10:47017" }
]
}
)
注意因为你的mongodb是需要对外的,因此rs中填写的host也应该需要能够对外访问的地址,如果直接执行rs.initiate()则使用当前容器的ip信息。
2. 增加认证
首先修改docker-compose设置系统的用户名和密码到环境变量中
version: "3"
services:
main:
image: mongo:4.4
container_name: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 12345678
ports:
- 47017:27017
# 可选的数据挂载
volumes:
- /mongo/conf:/conf
- /mongo/mongosh-1.8.0-linux-x64/bin:/root/bin
- /mongo/data:/data/db
restart: always
entrypoint: [ "/usr/bin/mongod", "-f", "/conf/mongo.conf"]
利用openssl生成mongodb复制集所需要的证书文件, 注意给权限。
openssl rand -base64 756 > /mongo/mongodbKeyfile.key
chmod 400 /mongo/mongodbKeyfile.key
然后修改mongo.conf配置
dbpath=/data/db
bind_ip=0.0.0.0
port=27017
auth=true
replSet=rs0
keyFile=/conf/mongodbKeyfile.key
基于docker-compose启动,进入容器利用mongosh 初始化副本集,需注意要先认证
use admin;
db.auth('root','12345678')
rs.initiate({
_id: "rs0",
version: 1,
members: [
{ _id: 0, host : "192.168.100.10:47017" }
]
}
)
3. 重新配置副本集
可能存在某一些原因导致需要重新配置副本集那么可以采取如下方案,首先修改配置文件时mongodb单节点运行并且没有权限认证
dbpath=/data/db
bind_ip=0.0.0.0
port=27017
# auth=true
# replSet=rs0
# keyFile=/conf/mongodbKeyfile.key
再启动mongodb程序,利用mongosh进入到mongodb中删除 local 库 中的数据
use local
db.dropDatabase()
然后再重新执行 1 或者 2 的操作过程即可