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

smdnsysy  于 2023-03-01  发布在  Docker
关注(0)|答案(7)|浏览(400)

我想创建一个带有Mongo示例的Docker容器。特别是,我想创建一个只有一个节点的副本集(因为我对事务感兴趣,而事务只适用于副本集)。
停靠文件

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

docker-compose.yml

version: "3"
services:
  db:
    build:
      dockerfile: Dockerfile
      context: .
    ports:
      - "27017:27017"

如果我单独使用Dockerfile,一切正常,而如果我使用docker-compose,它就不工作了:事实上,如果我随后登录到容器,我会得到提示为rs0:OTHER>而不是rs0:PRIMARY>
我查阅了这些链接,但提出的解决方案不起作用:
https://github.com/docker-library/mongo/issues/246#issuecomment-382072843https://github.com/docker-library/mongo/issues/249#issuecomment-381786889

2admgd59

2admgd591#

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

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:

如果rs.initiate()在运行后确实需要,它会使用Docker的健康检查(带有启动延迟)偷偷地进入rs.initiate()
创建密钥文件。

麦克:

openssl rand -base64 741 > keyfile
chmod 600 keyfile

Linux操作系统:

openssl rand -base64 756 > keyfile
chmod 600 keyfile
sudo chown 999 keyfile
sudo chgrp 999 keyfile
k97glaaz

k97glaaz2#

上面的答案在后来的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:

./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"]

这个Dockerfile适合于开发,但是您肯定希望在生产中挂载一个安全生成的持久性keyfile(因此删除整个RUN命令)。

qcbq4gxm

qcbq4gxm3#

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

yfwxisqw

yfwxisqw4#

我不得不围绕ChangeStreams做一些类似的测试,这些测试只有在将mongo作为副本集运行时才可用。我不记得我是从哪里得到这个的,所以我不能详细解释它,但它确实对我有用。下面是我的设置:

    • 停靠文件**
FROM mongo:5.0.3
RUN echo "rs.initiate({'_id':'rs0', members: [{'_id':1, 'host':'127.0.0.1:27017'}]});" > "/docker-entrypoint-initdb.d/init_replicaset.js"
RUN echo "12345678" > "/tmp/key.file"
RUN chmod 600 /tmp/key.file
RUN chown 999:999 /tmp/key.file

CMD ["mongod", "--replSet", "rs0", "--bind_ip_all", "--keyFile", "/tmp/key.file"]
    • 停靠-编写. yml**
version: '3.7'

services:
  mongo:
    build: .
    restart: always
    ports: 
      - 27017:27017
    healthcheck:
      test: test $$(echo "rs.initiate().ok || rs.status().ok" | mongo -u admin -p pass --quiet) -eq 1
      interval: 10s
      start_period: 30s
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: pass
      MONGO_INITDB_DATABASE: test

运行docker-compose up,你应该很好。
连接字符串:mongodb://admin:pass@localhost:27017/test
注:显然,您不应该在生产中使用此功能,如果安全性是一个问题,请调整Dockerfile中的键"12345678"。

wljmcqd8

wljmcqd85#

我无法让这些例子中的任何一个工作,所以在谷歌上搜索了几个小时之后,我终于找到了一些对我的本地开发来说足够好的东西,它不需要授权。这可能会破坏你的交易,但它看起来确实像一个复制集一样工作--所以事务看起来像预期的那样工作。
无论如何,只要用你想要的数据库名称替换YOUR_DB_NAME_HERE就可以了。我在启动时在这个数据库中创建了一个init集合,但是如果它不能满足你的需要,你可以在localdev-mongo服务入口点中删除这段代码;只是确保不要删除rs.initiate脚本/调用,因为这是初始化副本集所必需的。

version: '3.7'
services:
  your-service:
    build:
      context: .
      dockerfile: Dockerfile
    links:
      - localdev-mongo
    container_name: your-service
    environment:
      MONGO_APP_DATABASE: ${YOUR_DB_NAME_HERE}
      MONGO_CONNECTION_STRING: mongodb://localdev-mongo:27017/?directConnection=true&tls=false
    command: ${your app run command}
    depends_on:
      - localdev-mongo
    restart: unless-stopped
  localdev-mongo:
    image: mongo:latest
    environment:
      MONGO_APP_DATABASE: ${YOUR_DB_NAME_HERE}
      MONGO_REPLICA_HOST: host.docker.internal
      MONGO_REPLICA_PORT: 27018
    container_name: localdev-mongo
    entrypoint: >
      /bin/bash -c '
      echo "rs.initiate()" > /docker-entrypoint-initdb.d/1-init-replicaset.js &&
      echo "db = db.getSiblingDB(process.env[$0]);" > /docker-entrypoint-initdb.d/2-init-db-collection.js &&
      echo "db.createCollection($1, { capped: false });" >> /docker-entrypoint-initdb.d/2-init-db-collection.js &&
      echo "db.init.insert([{ message: $2 }]);" >> /docker-entrypoint-initdb.d/2-init-db-collection.js &&
      /usr/local/bin/docker-entrypoint.sh mongod --replSet rs0 --bind_ip_all --noauth' "'MONGO_APP_DATABASE'" "'init'" "'db initialized successfully'"
    expose:
      - 27017
    ports:
      - "27017:27017"
    volumes:
      - mongodb-data:/data/db
    restart: unless-stopped

volumes:
  mongodb-data:
snz8szmq

snz8szmq6#

如果您只需要通过docker-compose.yml创建MongoDB的单节点副本集,您可以简单地使用以下命令:

mongodb:
  image: mongo:5
  restart: always
  command: ["--replSet", "rs0", "--bind_ip_all"]
  ports:
    - 27018:27017
  healthcheck:
    test: mongo --eval "rs.initiate()"
    start_period: 5s
pod7payv

pod7payv7#

这一个对我来说很好:

version: '3.4'

services:
  ludustack-db:
      container_name: ludustack-db
      command: mongod --auth
      image: mongo:latest
      hostname: mongodb
      ports:
      - '27017:27017'
      env_file:
      - .env
      environment:
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
      - MONGO_INITDB_DATABASE=${MONGO_INITDB_DATABASE}
      - MONGO_REPLICA_SET_NAME=${MONGO_REPLICA_SET_NAME}
      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: 60s
        start_period: 60s

相关问题