0

我在我的代码中使用 MongoDB 更改流,需要创建一个启用更改流的 MongoDB docker 映像。问题是应该首先使用默认设置启动 mongod 以允许创建用户、文档等。然后应该停止 mongod。然后应该将副本集添加到 mongod.conf 以启用更改流:

# mongod.conf
replication:
  replSetName: rs0
  oplogSizeMB: 100

之后应该再次启动 mongod 并由 MongoDB shell 初始化副本集:

rs.slaveOk()
rs.initiate()
rs.initiate({_id:"rs0", members: [{"_id":1, "host":"127.0.0.1:27017"}]})

MogodDB 3.6基础镜像提供了初始化功能。你知道如何启动 mongod,初始化 DB 然后停止它并重新配置吗?

UPD:我需要初始化数据库然后添加副本集。因此,我需要使用默认的 mongod.conf 运行 mongod,创建用户和集合,然后使用另一个启用了副本集的 mongod、conf 重新启动 mongod。我不能用官方的 MongoDB 图像来做到这一点。我已经在 Ubuntu 映像上安装了 MongoDB 3.6.12。在 bash shell 中手动运行设置命令后,我的 MongoDB 容器运行良好,但相同的指令在 Dockerfile 中不起作用这是命令

RUN mongod --fork --config /etc/mongod.conf \
     && mongo < /opt/init_mongodb.js \
     && mongod --shutdown --dbpath /var/lib/mongodb \
     && cp /etc/mongod.conf /etc/mongod.conf.orig \
     && mongod --fork --config /opt/mongod.conf \
     && mongo -u "root" -p "root" --authenticationDatabase "admin" <  /opt/reconfig_mongodb.js \

从 Dockerfile 运行此命令时,出现以下错误

> backend@1.0.0 start /usr/src/app
> npm run babelserver

> backend@1.0.0 babelserver /usr/src/app
> babel-node --presets es2015 index.js

(node:41) UnhandledPromiseRejectionWarning: MongoError: not master and slaveOk=false
    at queryCallback (/usr/src/app/node_modules/mongodb-core/lib/cursor.js:248:25)
    at /usr/src/app/node_modules/mongodb-core/lib/connection/pool.js:532:18
    at processTicksAndRejections (internal/process/task_queues.js:82:9)
(node:41) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
4

3 回答 3

2

我认为这不是设置副本集的干净方式。它真的应该简单得多。

无需在后台模式下运行其中一个成员,设置副本集,保存配置文件,关闭进程,最后从保存的配置文件开始,您可以只运行一个额外的“帮助器”容器(也是一个 mongodb 图像)其唯一目的是在不充当成员的情况下设置 mongodb 副本集。

与此类似的东西可以完成这项工作:

docker-compose.yaml

version: '3'
services:
  mongodb-rs0-1:
    image: ${your_image}
    ports: [27018:27018]
    environment:
      - PORT=27018
      - MONGO_RS=rs0/mongodb-rs0-1:27018,mongodb-rs0-2:27019,mongodb-rs0-3:27020
    volumes:
    - ./db/rs0-1:/data/db
  mongodb-rs0-2:
    image: ${your_image}
    ports: [27019:27019]
    environment:
      - PORT=27019
      - MONGO_RS=rs0/mongodb-rs0-1:27018,mongodb-rs0-2:27019,mongodb-rs0-3:27020
    volumes:
    - ./db/rs0-2:/data/db
  mongodb-rs0-3:
    image: ${your_image}
    ports: [27020:27020]
    environment:
      - PORT=27020
      - MONGO_RS=rs0/mongodb-rs0-1:27018,mongodb-rs0-2:27019,mongodb-rs0-3:27020
    volumes:
    - ./db/rs0-3:/data/db
  mongodb-replicator:
    image: ${your_image}
    environment:
      - PRIMARY=mongodb-rs0-1:27018
    depends_on:
      - mongodb-rs0-1
      - mongodb-rs0-2
      - mongodb-rs0-3
networks:
  default:
    external:
      name: mongo

container_start.sh 中

#!/bin/sh

if [ -z "$PRIMARY" ]; then
  # Member container 
  docker-entrypoint.sh --replSet rs0 --smallfiles --oplogSize 128 --port "${PORT-27017}"
else
  # Replicator container
  until mongo "$PRIMARY" /app/replicaset-setup.js; do
      sleep 10
  done

fi
于 2020-04-09T15:54:31.933 回答
1

即使我花了几个小时才弄清楚,实际上设置一个启用复制的 dockerized mongodb 实例非常容易(它允许使用更改流。)

将这两个放在同一个文件夹中:

Dockerfile

FROM mongo:4.4
ADD ./init_replicaset.js /docker-entrypoint-initdb.d/init_replicaset.js
CMD ["mongod", "--replSet", "rs0", "--bind_ip_all"]

init_replicaset.js

rs.initiate({'_id':'rs0', members: [{'_id':1, 'host':'127.0.0.1:27017'}]});

注意:目录中的所有 .js/.sh 文件都会在/docker-entrypoint-initdb.dmongo 实例初始化时自动运行,这就是它起作用的原因。

在同一文件夹中,运行以下命令:

docker build . -t mongo_repl

docker run -i -p 27017:27017 mongo_repl

而已!您现在应该有一个正在运行且启用复制的 mongodb 实例。

于 2020-08-27T17:44:57.723 回答
0

通过在容器启动时初始化副本集来解决。此脚本在 docker 文件中设置为 ENTRYPOINT

#!/bin/sh
# start mongod, initialize replica set
mongod --fork --config /opt/mongod.conf
mongo --quiet < /opt/replica.js
# restart mongod    
mongod --shutdown --dbpath /var/lib/mongodb
mongod --config /opt/mongod.conf

副本.js

rs.slaveOk()
rs.initiate()
rs.initiate({_id:"rs0", members: [{"_id":1, "host":"127.0.0.1:27017"}]})
于 2019-05-17T23:13:06.977 回答