├── .gitignore ├── LICENSE ├── README.md ├── docker-compose.yml └── example ├── mongoose.js └── transaction.js /.gitignore: -------------------------------------------------------------------------------- 1 | mongo/* 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Vahid V. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mongo-RS 2 | 3 | Mongo replication set with four nodes, run and start with docker compose: 4 | 5 | ```sh 6 | sudo mkdir -p -m 777 mongo/primary 7 | sudo chown -R 1001 mongo 8 | ``` 9 | 10 | > NOTE: As this is a non-root container, the mounted files and directories must have the proper permissions for the UID 1001. 11 | 12 | ```sh 13 | docker-compose up -d 14 | ``` 15 | 16 | > NOTE: It will take time to initiate for first time 17 | 18 | Add this lines to `/etc/hosts`: 19 | 20 | ```sh 21 | 127.0.0.1 mongodb-primary 22 | 127.0.0.1 mongodb-secondary-1 23 | 127.0.0.1 mongodb-secondary-2 24 | 127.0.0.1 mongodb-arbiter 25 | ``` 26 | 27 | ## Connection URI 28 | 29 | `mongodb://root:password123@mongodb-primary:27017,mongodb-secondary-1:27018,mongodb-secondary-2:27019,mongodb-arbiter:27020/?replicaSet=rs0&authSource=admin` 30 | 31 | ### Reference 32 | 33 | - https://github.com/bitnami/containers/tree/main/bitnami/mongodb 34 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | services: 4 | mongodb-primary: 5 | image: docker.io/bitnami/mongodb:7.0 6 | container_name: mongodb-primary 7 | hostname: mongodb-primary 8 | networks: 9 | default: 10 | expose: 11 | - 27017 12 | ports: 13 | - 27017:27017 14 | environment: 15 | - MONGODB_ADVERTISED_HOSTNAME=mongodb-primary 16 | - MONGODB_REPLICA_SET_MODE=primary 17 | - MONGODB_ROOT_PASSWORD=password123 18 | - MONGODB_REPLICA_SET_NAME=rs0 19 | - MONGODB_REPLICA_SET_KEY=replicasetkey123 20 | - BITNAMI_DEBUG=true 21 | volumes: 22 | - "./mongo/primary:/bitnami/mongodb" 23 | 24 | mongodb-secondary-1: 25 | image: docker.io/bitnami/mongodb:7.0 26 | container_name: mongodb-secondary-1 27 | hostname: mongodb-secondary-1 28 | depends_on: 29 | - mongodb-primary 30 | networks: 31 | default: 32 | expose: 33 | - 27018 34 | ports: 35 | - 27018:27017 36 | environment: 37 | - MONGODB_ADVERTISED_HOSTNAME=mongodb-secondary-1 38 | - MONGODB_REPLICA_SET_MODE=secondary 39 | - MONGODB_INITIAL_PRIMARY_HOST=mongodb-primary 40 | - MONGODB_INITIAL_PRIMARY_PORT_NUMBER=27017 41 | - MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD=password123 42 | - MONGODB_REPLICA_SET_NAME=rs0 43 | - MONGODB_REPLICA_SET_KEY=replicasetkey123 44 | 45 | mongodb-secondary-2: 46 | image: docker.io/bitnami/mongodb:7.0 47 | container_name: mongodb-secondary-2 48 | hostname: mongodb-secondary-2 49 | depends_on: 50 | - mongodb-primary 51 | networks: 52 | default: 53 | expose: 54 | - 27019 55 | ports: 56 | - 27019:27017 57 | environment: 58 | - MONGODB_ADVERTISED_HOSTNAME=mongodb-secondary-2 59 | - MONGODB_REPLICA_SET_MODE=secondary 60 | - MONGODB_INITIAL_PRIMARY_HOST=mongodb-primary 61 | - MONGODB_INITIAL_PRIMARY_PORT_NUMBER=27017 62 | - MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD=password123 63 | - MONGODB_REPLICA_SET_NAME=rs0 64 | - MONGODB_REPLICA_SET_KEY=replicasetkey123 65 | 66 | mongodb-arbiter: 67 | image: docker.io/bitnami/mongodb:7.0 68 | container_name: mongodb-arbiter 69 | hostname: mongodb-arbiter 70 | depends_on: 71 | - mongodb-primary 72 | networks: 73 | default: 74 | expose: 75 | - 27020 76 | ports: 77 | - 27020:27017 78 | environment: 79 | - MONGODB_ADVERTISED_HOSTNAME=mongodb-arbiter 80 | - MONGODB_REPLICA_SET_MODE=arbiter 81 | - MONGODB_INITIAL_PRIMARY_HOST=mongodb-primary 82 | - MONGODB_INITIAL_PRIMARY_PORT_NUMBER=27017 83 | - MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD=password123 84 | - MONGODB_REPLICA_SET_NAME=rs0 85 | - MONGODB_REPLICA_SET_KEY=replicasetkey123 86 | -------------------------------------------------------------------------------- /example/mongoose.js: -------------------------------------------------------------------------------- 1 | // If on a linux server, use the hostname provided by the docker compose file 2 | // e.g. HOSTNAME = mongodb-primary, mongo-secondary-1, mongo-secondary-2, mongo-arbiter 3 | 4 | // If on MacOS add the following to your /etc/hosts file. 5 | // 127.0.0.1 mongodb-primary 6 | // 127.0.0.1 mongo-secondary-1 7 | // 127.0.0.1 mongo-secondary-2 8 | // 127.0.0.1 mongo-arbiter 9 | // And use localhost as the HOSTNAME 10 | mongoose.connect( 11 | "mongodb://:27017,:27018,:27019/", 12 | { 13 | useNewUrlParser: true, 14 | useFindAndModify: false, // optional 15 | useCreateIndex: true, 16 | replicaSet: "rs0", // We use this from the entrypoint in the docker-compose file 17 | } 18 | ); 19 | -------------------------------------------------------------------------------- /example/transaction.js: -------------------------------------------------------------------------------- 1 | async function transaction() { 2 | // Start the transaction. 3 | const session = await ModelA.startSession(); 4 | session.startTransaction(); 5 | 6 | try { 7 | const options = { session }; 8 | 9 | // Try and perform operation on Model. 10 | const a = await ModelA.create([{ ...args }], options); 11 | 12 | // If the first operation succeeds this next one will get called. 13 | await ModelB.create([{ ...args }], options); 14 | 15 | // If all succeeded with no errors, commit and end the session. 16 | await session.commitTransaction(); 17 | session.endSession(); 18 | return a; 19 | } catch (e) { 20 | // If any error occured, the whole transaction fails and throws error. 21 | // Undos changes that may have happened. 22 | await session.abortTransaction(); 23 | session.endSession(); 24 | throw e; 25 | } 26 | } --------------------------------------------------------------------------------