📜  mongodb docker-compose 副本集 (1)

📅  最后修改于: 2023-12-03 15:03:01.049000             🧑  作者: Mango

MongoDB Docker Compose 副本集

介绍

本文将介绍如何使用 Docker Compose 在本地或云环境中运行 MongoDB 副本集。

MongoDB 副本集是一个自我复制的 MongoDB 数据库集群,它包含多个数据节点和一个选举器节点。它提供了高可用性和横向扩展的能力。

Docker Compose 是 Docker 官方提供的工具,它可以定义和运行多个 Docker 容器应用。使用 Docker Compose 可以简化 MongoDB 副本集的部署和运维。

本教程将使用 Docker Compose 部署和运行一个三节点的 MongoDB 副本集,包括一个主节点和两个从节点,并测试其高可用性和数据复制功能。

准备工作

在开始本教程之前,您需要确保已经在本地或云环境中安装好 Docker 和 Docker Compose 工具。如果您还没有安装,请参考官方文档进行安装。

编写 Docker Compose 文件

首先,您需要在本地创建一个新的目录,命名为 mongodb-aws,用于存放我们的 Docker Compose 文件和其他配置文件。

创建 docker-compose.yml 文件并添加以下内容:

version: "3.7"

services:
  mongodb-1:
    image: mongo
    restart: always
    container_name: mongodb-1
    volumes:
      - ./data/mongodb-1:/data/db
      - ./config/mongodb-1:/etc/mongo
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
    ports:
      - 27017:27017
    networks:
      mongodb-aws:
        ipv4_address: 172.28.1.10
    command: mongod --replSet rs0 --bind_ip_all --config /etc/mongo/mongod.conf

  mongodb-2:
    image: mongo
    restart: always
    container_name: mongodb-2
    volumes:
      - ./data/mongodb-2:/data/db
      - ./config/mongodb-2:/etc/mongo
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
    networks:
      mongodb-aws:
        ipv4_address: 172.28.1.11
    command: mongod --replSet rs0 --bind_ip_all --config /etc/mongo/mongod.conf

  mongodb-3:
    image: mongo
    restart: always
    container_name: mongodb-3
    volumes:
      - ./data/mongodb-3:/data/db
      - ./config/mongodb-3:/etc/mongo
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
    networks:
      mongodb-aws:
        ipv4_address: 172.28.1.12
    command: mongod --replSet rs0 --bind_ip_all --config /etc/mongo/mongod.conf

networks:
  mongodb-aws:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16

以上 Docker Compose 文件定义了三个服务,分别是三个 MongoDB 节点,通过 volumes 挂载数据卷和配置文件,通过 networks 指定了节点之间的通信网络,通过 command 指定了启动命令。

将以上 YAML 代码保存为 docker-compose.yml 文件,并存放到 mongodb-aws 目录下。

然后创建一个新目录,命名为 data,用于存放 MongoDB 数据文件,同时在 data 目录下为每个节点创建一个子目录:

$ mkdir -p data/mongodb-1 data/mongodb-2 data/mongodb-3

接着,在 mongodb-aws 目录下创建一个新的目录,命名为 config,用于存放 MongoDB 配置文件,同时在 config 目录下为每个节点创建一个子目录,并在每个子目录下分别创建一个 mongod.conf 配置文件,用于指定节点的相关配置:

$ mkdir -p config/mongodb-1 config/mongodb-2 config/mongodb-3

$ cat > config/mongodb-1/mongod.conf << EOF
replication:
    replSetName: rs0
    oplogSizeMB: 1024

net:
    port: 27017
    bindIp: 0.0.0.0

security:
    authorization: enabled

systemLog:
    destination: file
    path: /var/log/mongodb/mongod.log
    logAppend: true
EOF

$ cat > config/mongodb-2/mongod.conf << EOF
replication:
    replSetName: rs0
    oplogSizeMB: 1024

net:
    port: 27017
    bindIp: 0.0.0.0

security:
    authorization: enabled

systemLog:
    destination: file
    path: /var/log/mongodb/mongod.log
    logAppend: true
EOF

$ cat > config/mongodb-3/mongod.conf << EOF
replication:
    replSetName: rs0
    oplogSizeMB: 1024

net:
    port: 27017
    bindIp: 0.0.0.0

security:
    authorization: enabled

systemLog:
    destination: file
    path: /var/log/mongodb/mongod.log
    logAppend: true
EOF

以上配置中,我们指定了每个节点的 replSetNamers0,将数据库端口设置为 27017,设置了授权模式为 enabled,同时启用了日志记录功能,将日志输出到 /var/log/mongodb/mongod.log 文件中。

启动 MongoDB 副本集

现在,我们已经编写好了 Docker Compose 文件和配置文件,可以开始启动 MongoDB 副本集了。

mongodb-aws 目录下执行以下命令:

$ docker-compose up -d

以上命令将会创建三个 MongoDB 容器实例,并运行它们。-d 参数表示在后台运行。

启动后,通过以下命令可以查看所有容器实例的运行状态:

$ docker-compose ps

Name                 Command               State           Ports         
-----------------------------------------------------------------------
mongodb-1   mongod --replSet rs0 --bin ...   Up      0.0.0.0:27017->27017/tcp
mongodb-2   mongod --replSet rs0 --bin ...   Up                           
mongodb-3   mongod --replSet rs0 --bin ...   Up                           

可以看到,三个 MongoDB 节点都启动成功了。

配置 MongoDB 副本集

虽然我们已经在 Docker Compose 中指定了 replSetNamers0,但是我们还需要在其中的一个节点上运行一个初始化命令,来创建一个 MongoDB 副本集,并指定其他节点的连接信息和角色。

我们选择 mongodb-1 节点来运行初始化命令。

首先,进入到 mongodb-1 容器中:

$ docker exec -it mongodb-1 bash

当进入容器后,我们需要先登录到 MongoDB Shell,然后执行初始化命令。

# mongo -u root -p example --authenticationDatabase=admin

> rs.initiate({
    _id: 'rs0',
    members: [
        { _id: 0, host: 'mongodb-1:27017' },
        { _id: 1, host: 'mongodb-2:27017' },
        { _id: 2, host: 'mongodb-3:27017' }
    ]
})

以上命令中,我们使用 rs.initiate() 函数来创建一个新的 MongoDB 副本集,并指定了三个节点的连接信息和角色。

执行完成后,可以输入 rs.status() 查看 MongoDB 副本集的状态信息:

> rs.status()
{
    "set" : "rs0",
    "date" : ISODate("2021-07-10T10:12:39.941Z"),
    "myState" : 1,
    "term" : NumberLong(1),
    "syncingTo" : "",
    "syncSourceHost" : "",
    "syncSourceId" : -1,
    "heartbeatIntervalMillis" : NumberLong(2000),
    "electionTimeoutMillis" : NumberLong(10000),
    "members" : [
        {
            "_id" : 0,
            "name" : "mongodb-1:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 61,
            "optime" : {
                "ts" : Timestamp(1625913117, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1625913117, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2021-07-10T09:38:37Z"),
            "optimeDurableDate" : ISODate("2021-07-10T09:38:37Z"),
            "lastHeartbeat" : ISODate("2021-07-10T10:12:38.274Z"),
            "lastHeartbeatRecv" : ISODate("2021-07-10T10:12:39.361Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncingTo" : "",
            "syncSourceHost" : "",
            "syncSourceId" : -1,
            "infoMessage" : "",
            "electionTime" : Timestamp(1625913107, 1),
            "electionDate" : ISODate("2021-07-10T09:38:27Z"),
            "configVersion" : 1
        },
        {
            "_id" : 1,
            "name" : "mongodb-2:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 58,
            "optime" : {
                "ts" : Timestamp(1625913117, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1625913117, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2021-07-10T09:38:37Z"),
            "optimeDurableDate" : ISODate("2021-07-10T09:38:37Z"),
            "lastHeartbeat" : ISODate("2021-07-10T10:12:38.274Z"),
            "lastHeartbeatRecv" : ISODate("2021-07-10T10:12:38.671Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncingTo" : "mongodb-1:27017",
            "syncSourceHost" : "mongodb-1:27017",
            "syncSourceId" : 0,
            "infoMessage" : "",
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "mongodb-3:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 59,
            "optime" : {
                "ts" : Timestamp(1625913117, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1625913117, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2021-07-10T09:38:37Z"),
            "optimeDurableDate" : ISODate("2021-07-10T09:38:37Z"),
            "lastHeartbeat" : ISODate("2021-07-10T10:12:38.274Z"),
            "lastHeartbeatRecv" : ISODate("2021-07-10T10:12:39.361Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncingTo" : "mongodb-1:27017",
            "syncSourceHost" : "mongodb-1:27017",
            "syncSourceId" : 0,
            "infoMessage" : "",
            "configVersion" : 1
        }
    ],
    "ok" : 1,
    "$clusterTime" : {
        "clusterTime" : Timestamp(1625913117, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    },
    "operationTime" : Timestamp(1625913117, 1)
}

可以看到,每个节点都成功连接到 MongoDB 副本集,并成为了 PRIMARY 或 SECONDARY 角色。

测试 MongoDB 副本集高可用性和数据复制功能

接下来,我们可以进一步测试 MongoDB 副本集的高可用性和数据复制功能。

首先,我们可以在 mongodb-1 主节点上创建一个新数据库和一个新集合:

> use mydb
switched to db mydb

> db.createCollection('mycol')
{ "ok" : 1 }

然后,我们可以在 mongodb-2 从节点上查看新集合是否已经复制过来:

> use mydb
switched to db mydb

> db.mycol.find()

可以看到,返回了新集合中的数据,证明数据已经成功复制到了从节点。

接下来,我们可以模拟 mongodb-1 主节点宕机的情况,停止该容器实例:

$ docker-compose stop mongodb-1

停止后,我们可以在 mongodb-2 从节点上再次查看集合数据:

> use mydb
switched to db mydb

> db.mycol.find()

可以看到,从节点成功接替了主节点的角色,数据仍然可以正常访问,从节点已被晋升为 PRIMARY 角色。

至此,我们已经成功在 Docker Compose 中部署和运行了一个 MongoDB 副本集,并进行了测试验证。

结论

MongoDB 副本集是一个高可用性、可扩展性强的 NoSQL 数据库解决方案。使用 Docker Compose 部署和运行 MongoDB 副本集可以大大简化其部署和运维的难度,同时提供了更高的效率和灵活性。

本文介绍了如何通过 Docker Compose 部署和运行 MongoDB 副本集,并进行了测试验证。希望本文对您有所帮助,谢谢阅读!