简体   繁体   English

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

[英]Mongo container with a replica set with only one node in docker-compose

I want to create a Docker container with an instance of Mongo.我想创建一个带有 Mongo 实例的 Docker 容器。 In particular, I would like to create a replica set with only one node (since I'm interested in transactions and they are only available for replica sets).特别是,我想创建一个只有一个节点的副本集(因为我对事务感兴趣并且它们仅适用于副本集)。

Dockerfile Dockerfile

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

docker-compose.yml docker-compose.yml

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

If I use the Dockerfile alone everything is fine, while if I use docker-compose it does not work: in fact if I then log to the container I got prompted as rs0:OTHER> instead of rs0:PRIMARY> .如果我单独使用 Dockerfile 一切都很好,而如果我使用 docker-compose 它不起作用:事实上,如果我然后登录到容器,我得到的提示是rs0:OTHER>而不是rs0:PRIMARY>

I consulted these links but the solutions proposed are not working:我查阅了这些链接,但提出的解决方案不起作用:

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

You still need to issue replSetInitiate even if there's only one node in the RS.即使 RS 中只有一个节点,您仍然需要发出replSetInitiate

See also here .另请参见此处

This is the compose file I have used for a while now for local development.这是我现在用于本地开发的 compose 文件。 You can remove the keyfile pieces if you don't need to connect via SSL.如果您不需要通过 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:

It uses Docker's health check (with a startup delay) to sneak in the rs.initiate() if it actually needs it after it's already running.它使用 Docker 的健康检查(带有启动延迟)来潜入rs.initiate()如果它在运行后确实需要它。

To create a keyfile.创建密钥文件。

Mac:苹果电脑:

openssl rand -base64 741 > keyfile
chmod 600 keyfile

Linux: Linux:

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

I had to do something similar to build tests around ChangeStreams which are only available when running mongo as a replica set.我必须做一些类似的事情来围绕 ChangeStreams 构建测试,这些测试仅在将 mongo 作为副本集运行时可用。 I don't remember where I pulled this from, so I can't explain it in detail but it does work for me.我不记得我是从哪里得出的,所以我无法详细解释它,但它确实对我有用。 Here is my setup:这是我的设置:

Dockerfile Dockerfile

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

docker-compose.yml docker-compose.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

Run docker-compose up and you should be good.运行docker-compose up可以了。

Connection String: mongodb://admin:pass@localhost:27017/test连接字符串: mongodb://admin:pass@localhost:27017/test

Note: You shouldn't use this in production obviously, adjust the key "12345678" in the Dockerfile if security is a concern.注意:你显然不应该在生产中使用它,如果安全是一个问题,请调整 Dockerfile 中的密钥“12345678”。

If you just need single node replica set of MongoDB via docker-compose.yml you can simply use this:如果您只需要 MongoDB 通过 docker-compose.yml 的单节点副本集,您可以简单地使用:

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

The top answer stopped working for me in later MongoDB and Docker versions.在后来的 MongoDB 和 Docker 版本中,最佳答案对我不起作用。 Particularly because rs.initiate().ok would throw an error if the replica set was already initiated, causing the whole command to fail.特别是因为如果副本集已经启动, rs.initiate().ok会抛出错误,导致整个命令失败。 In addition, connecting from another container was failing because the replica set's sole member had some random host, which wouldn't allow the connection.此外,从另一个容器连接失败,因为副本集的唯一成员有一些随机主机,不允许连接。 Here's my new docker-compose.yml :这是我的新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:

Inside ./mongo/ , I have a custom Dockerfile that looks like:./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"]

This Dockerfile is suitable for development, but you'd definitely want a securely generated and persistent keyfile to be mounted in production (and therefore strike the entire RUN command).这个Dockerfile适合开发,但您肯定希望在生产中安装一个安全生成且持久的keyfile文件(因此敲击整个RUN命令)。

This one works fine for me:这对我来说很好用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM