带有副本集的 Mongo 容器,在 docker-compose 中只有一个节点

Iu *_*Tub 5 mongodb docker replicaset docker-compose

我想创建一个带有 Mongo 实例的 Docker 容器。特别是,我想创建一个只有一个节点的副本集(因为我对事务感兴趣并且它们仅可用于副本集)。

文件

FROM mongo
RUN echo "rs.initiate();" > /docker-entrypoint-initdb.d/replica-init.js
CMD ["--replSet", "rs0"]
Run Code Online (Sandbox Code Playgroud)

docker-compose.yml

version: "3"
services:
  db:
    build:
      dockerfile: Dockerfile
      context: .
    ports:
      - "27017:27017"
Run Code Online (Sandbox Code Playgroud)

如果我单独使用 Dockerfile 一切都很好,而如果我使用 docker-compose 它不起作用:事实上,如果我然后登录到容器,我得到的提示rs0:OTHER>rs0:PRIMARY>.

我查阅了这些链接,但提出的解决方案不起作用:

https://github.com/docker-library/mongo/issues/246#issuecomment-382072843 https://github.com/docker-library/mongo/issues/249#issuecomment-381786889

Her*_*del 24

这是我在本地开发中使用了一段时间的撰写文件。keyfile如果您不需要通过 SSL 连接,则可以删除这些部分。

version: "3.8"
services:
  mongodb:
    image : mongo:4
    container_name: mongodb
    hostname: mongodb
    restart: on-failure
    environment:
      - PUID=1000
      - PGID=1000
      - MONGO_INITDB_ROOT_USERNAME=mongo
      - MONGO_INITDB_ROOT_PASSWORD=mongo
      - MONGO_INITDB_DATABASE=my-service
      - MONGO_REPLICA_SET_NAME=rs0
    volumes:
      - mongodb4_data:/data/db
      - ./:/opt/keyfile/
    ports:
      - 27017:27017
    healthcheck:
      test: test $$(echo "rs.initiate().ok || rs.status().ok" | mongo -u $${MONGO_INITDB_ROOT_USERNAME} -p $${MONGO_INITDB_ROOT_PASSWORD} --quiet) -eq 1
      interval: 10s
      start_period: 30s
    command: "--bind_ip_all --keyFile /opt/keyfile/keyfile --replSet rs0"
volumes:
  mongodb4_data:

Run Code Online (Sandbox Code Playgroud)

它使用 Docker 的运行状况检查(带有启动延迟)来rs.initiate()在运行后潜入是否确实需要它。

创建密钥文件。

苹果:

openssl rand -base64 741 > keyfile
chmod 600 keyfile
Run Code Online (Sandbox Code Playgroud)

Linux:

openssl rand -base64 756 > keyfile
chmod 600 keyfile
sudo chown 999 keyfile
sudo chgrp 999 keyfile
Run Code Online (Sandbox Code Playgroud)

  • 我在没有密钥文件的情况下尝试过,“mongod”表示没有密钥文件就无法启动副本集。按照您的指示进行操作后,效果很好。我能够使用 `mongodb://username:password@localhost:27017/?authSource=admin&readPreference=primary&ssl=false&replicaSet=rs0` 进行连接 (3认同)

T.J*_*ika 6

在后来的 MongoDB 和 Docker 版本中,最重要的答案不再对我有用。特别是因为rs.initiate().ok如果副本集已经启动,则会抛出错误,导致整个命令失败。此外,从另一个容器的连接失败,因为副本集的唯一成员有一些随机主机,该主机不允许连接。这是我的新docker-compose.yml

services:
  web:
    # ...
    environment:
      DATABASE_URL: mongodb://root:root@db/?authSource=admin&tls=false
  db:
    build:
      context: ./mongo/
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: root
    ports:
      - '27017:27017'
    volumes:
      - data:/data/db
    healthcheck:
      test: |
        test $$(mongosh --quiet -u root -p root --eval "try { rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: 'db' }] }).ok } catch (_) { rs.status().ok }") -eq 1
      interval: 10s
      start_period: 30s
volumes:
  data:
Run Code Online (Sandbox Code Playgroud)

在里面./mongo/,我有一个Dockerfile如下所示的自定义:

FROM mongo:6
RUN echo "password" > /keyfile \
  && chmod 600 /keyfile \
  && chown 999 /keyfile \
  && chgrp 999 /keyfile
CMD ["--bind_ip_all", "--keyFile", "/keyfile", "--replSet", "rs0"]
Run Code Online (Sandbox Code Playgroud)

Dockerfile适合开发,但您肯定希望安全生成并持久keyfile安装在生产中(因此需要执行整个RUN命令)。

  • 这只适用于我在测试命令中将名称设置为“localhost”而不是“db”时 (4认同)

D. *_* SM 0

即使 RS 中只有一个节点,您仍然需要发出replSetInitiate 。

另请参阅此处