prisma / docs

📚 Prisma Documentation
https://www.prisma.io/docs
Apache License 2.0
981 stars 772 forks source link

MongoDB: Add replica set example using docker-compose #3040

Open Jolg42 opened 2 years ago

Jolg42 commented 2 years ago

I think we should document the current MongoDB docker compose setup @millsp created, it might be the easiest one command setup (if you have docker compose). Also, because MongoDB Atlas is not great to use for tests, it will suffer with latency and concurrency.

https://github.com/prisma/prisma/blob/main/docker/docker-compose.yml#L91-L99 So

version: '3.7'

services:
  mongodb:
    build: ./mongodb_replica
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: root
      MONGO_REPLICA_HOST: localhost
      MONGO_REPLICA_PORT: 27017
    ports:
      - '27017:27017'

Note I changed the port from current setup to use the default port, it's the one people will expect.

https://github.com/prisma/prisma/blob/main/docker/mongodb_replica/Dockerfile

FROM mongo:4

# we take over the default & start mongo in replica set mode in a background task
ENTRYPOINT mongod --port $MONGO_REPLICA_PORT --replSet rs0 --bind_ip 0.0.0.0 & MONGOD_PID=$!; \
# we prepare the replica set with a single node and prepare the root user config
INIT_REPL_CMD="rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: '$MONGO_REPLICA_HOST:$MONGO_REPLICA_PORT' }] })"; \
INIT_USER_CMD="db.createUser({ user: '$MONGO_INITDB_ROOT_USERNAME', pwd: '$MONGO_INITDB_ROOT_PASSWORD', roles: [ 'root' ] })"; \
# we wait for the replica set to be ready and then submit the commands just above
until (mongo admin --port $MONGO_REPLICA_PORT --eval "$INIT_REPL_CMD && $INIT_USER_CMD"); do sleep 1; done; \
# we are done but we keep the container by waiting on signals from the mongo task
echo "REPLICA SET ONLINE"; wait $MONGOD_PID;

So when the docker-compose.yml and mongodb_replica/Dockerfile files are created, starting the replica set can be done with the following command

docker-compose up -d

and be accessed with the following conenction url

mongodb://root:root@localhost:27017/mydb?authSource=admin"

Note that this setup is only recommended for development.

Update: this works with MongoDB image v4 and v5 but fails with v6 because of https://www.mongodb.com/docs/manual/release-notes/6.0-compatibility/#legacy-mongo-shell-removed

chaoky commented 2 years ago

this setup gives me the following error

Node.js v17.8.0

error Command failed with exit code 1.

warning package.json: No license field

/node_modules/@prisma/client/runtime/index.js:41448

            reject2(new PrismaClientInitializationError(error2.message, this.config.clientVersion, error2.error_code));

                    ^

PrismaClientInitializationError: Database error. error code: unknown, error message: Server selection timeout: No available servers. Topology: { Type: Unknown, Servers: [ { Address: localhost:27017, Type: Unknown, Error: Address not available (os error 99) }, ] }

    at /node_modules/@prisma/client/runtime/index.js:41448:21 {

  clientVersion: '3.12.0',

  errorCode: undefined

}
janpio commented 2 years ago

Please report that at https://github.com/prisma/prisma and we can take a look at it @chaoky

masterbater commented 2 years ago

this setup gives me the following error

Node.js v17.8.0

error Command failed with exit code 1.

warning package.json: No license field

/node_modules/@prisma/client/runtime/index.js:41448

            reject2(new PrismaClientInitializationError(error2.message, this.config.clientVersion, error2.error_code));

                    ^

PrismaClientInitializationError: Database error. error code: unknown, error message: Server selection timeout: No available servers. Topology: { Type: Unknown, Servers: [ { Address: localhost:27017, Type: Unknown, Error: Address not available (os error 99) }, ] }

    at /node_modules/@prisma/client/runtime/index.js:41448:21 {

  clientVersion: '3.12.0',

  errorCode: undefined

}

This is much cleaner also uses Mongodb version 5 and no more adding shell scripts on entrypoint. If you used the main mongo docker you will have this error when using version 5 security.keyFile is required when authorization is enabled with replica sets. Bitnami/mongodb is verified so I think its ok to use

version: '3.8'
services:

  database:
    image: 'bitnami/mongodb:latest'
    environment:
      - MONGODB_ADVERTISED_HOSTNAME=127.0.0.1
      - MONGODB_REPLICA_SET_MODE=primary
      - MONGODB_ROOT_USER=anyuser
      - MONGODB_ROOT_PASSWORD=anypassword
      - MONGODB_REPLICA_SET_KEY=replicasetkey123
    ports:
      - '27017:27017'
    volumes:
      - 'mongo-db:/bitnami/mongodb'

volumes:
  mongo-db:
chaoky commented 2 years ago

@masterbater thanks a lot, something similar worked for me (on wsl 2)

services:
  gmb:
    build: .
    restart: always
    ports:
      - 3001:3001
    volumes:
      - ./keypair.json:/keypair.json
      - ./freeze-keypair.json:/freeze-keypair.json
      - ./settings.json:/settings.json
    depends_on:
      - mongo
    environment:
      DATABASE_URL: "mongodb://root:root@host.docker.internal:27017/config?replicaSet=replicaset"

  mongo:
    image: bitnami/mongodb:latest
    environment:
      - MONGODB_ADVERTISED_HOSTNAME=host.docker.internal
      - MONGODB_REPLICA_SET_MODE=primary
      - MONGODB_REPLICA_SET_KEY=replicasetkey123
      - MONGODB_ROOT_USER=root
      - MONGODB_ROOT_PASSWORD=root
    ports:
      - 27017:27017

https://github.com/docker/for-win/issues/6736

chaoky commented 2 years ago

but there's no host.docker.internal on linux, that will only work for mac/windows

chaoky commented 2 years ago

you can use

    extra_hosts:
      - "host.docker.internal:host-gateway"

in the mean time

chaoky commented 2 years ago

why do we have to use the host network anyway? this is so unusual

masterbater commented 2 years ago

You can use 127.0.0.1 or localhost during development.

On Tue, Apr 19, 2022, 9:58 AM Lordie, @.***> wrote:

why do we have to use the host network anyway? this is so unusual

— Reply to this email directly, view it on GitHub https://github.com/prisma/docs/issues/3040#issuecomment-1101917426, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGI6VFHTX4XO76OGTCW2YOTVFYHOBANCNFSM5SVKAUKA . You are receiving this because you were mentioned.Message ID: @.***>

mammadataei commented 2 years ago

I think it would be great to document the production configuration as well.

cnscorpions commented 1 year ago

@Jolg42 thank you, it works well now.

marisancans commented 1 year ago

Following @Jolg42 I have docker compose as

  mongo:
    build: ./mongodb_replica
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
      MONGO_REPLICA_HOST: localhost
      MONGO_REPLICA_PORT: 27017
    ports:
      - '27017:27017'

And mongodb_repilca folder Dockerfile is:

FROM mongo:4

# we take over the default & start mongo in replica set mode in a background task
ENTRYPOINT mongod --port $MONGO_REPLICA_PORT --replSet rs0 --bind_ip 0.0.0.0 & MONGOD_PID=$!; \
# we prepare the replica set with a single node and prepare the root user config
INIT_REPL_CMD="rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: '$MONGO_REPLICA_HOST:$MONGO_REPLICA_PORT' }] })"; \
INIT_USER_CMD="db.createUser({ user: '$MONGO_INITDB_ROOT_USERNAME', pwd: '$MONGO_INITDB_ROOT_PASSWORD', roles: [ 'root' ] })"; \
# we wait for the replica set to be ready and then submit the commands just above
until (mongo admin --port $MONGO_REPLICA_PORT --eval "$INIT_REPL_CMD && $INIT_USER_CMD"); do sleep 1; done; \
# we are done but we keep the container by waiting on signals from the mongo task
echo "REPLICA SET ONLINE"; wait $MONGOD_PID;

With DATABASE_URL=mongodb://root:example@mongo:27017/majoklis_db?authSource=admin

I cant get this to work after countless hours (this has been so far the most difficult database setup I have experienced yet :/ )


root@bb9c8e39cee1:/app/ss-ad-scraper# npx prisma db push
Prisma schema loaded from prisma/schema.prisma
Datasource "db": MongoDB database "majoklis_db" at "mongo:27017"
Error: MongoDB error
Kind: Server selection timeout: No available servers. Topology: { Type: ReplicaSetNoPrimary, Set Name: rs0, Max Set Version: 1, Max Election ID: 7fffffff0000000000000001, Servers: [ { Address: localhost:27017, Type: Unknown, Error: Kind: I/O error: Cannot assign requested address (os error 99), labels: {} } ] }, labels: {}
   0: schema_core::commands::schema_push::Calculate `from`
             at schema-engine/core/src/commands/schema_push.rs:29
   1: schema_core::state::SchemaPush
             at schema-engine/core/src/state.rs:436

I am trying to access the mongodb from another docker service, not local host. I see in error that it tries to access it by localhost:27017, but i think it should be mongo:27017 as i need to get to it from another service