{"id":37028317,"url":"https://github.com/silaev/mongodb-replica-set","last_synced_at":"2026-01-14T03:22:52.191Z","repository":{"id":44996986,"uuid":"212261171","full_name":"silaev/mongodb-replica-set","owner":"silaev","description":"Run MongoDB Atlas locally for testing","archived":false,"fork":false,"pushed_at":"2022-01-14T18:52:41.000Z","size":228,"stargazers_count":43,"open_issues_count":4,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2023-09-07T10:08:08.042Z","etag":null,"topics":["docker","java","mongodb","replica-set","testcontainers","transaction"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/silaev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-02T05:20:12.000Z","updated_at":"2023-09-07T10:08:08.043Z","dependencies_parsed_at":"2022-08-28T08:41:06.747Z","dependency_job_id":null,"html_url":"https://github.com/silaev/mongodb-replica-set","commit_stats":null,"previous_names":[],"tags_count":9,"template":null,"template_full_name":null,"purl":"pkg:github/silaev/mongodb-replica-set","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silaev%2Fmongodb-replica-set","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silaev%2Fmongodb-replica-set/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silaev%2Fmongodb-replica-set/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silaev%2Fmongodb-replica-set/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/silaev","download_url":"https://codeload.github.com/silaev/mongodb-replica-set/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silaev%2Fmongodb-replica-set/sbom","scorecard":{"id":823399,"data":{"date":"2025-08-11","repo":{"name":"github.com/silaev/mongodb-replica-set","commit":"48d826f8abc150f72632aa3683a81e7ecae80e06"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/25 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/gradle.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/silaev/mongodb-replica-set/gradle.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/silaev/mongodb-replica-set/gradle.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/silaev/mongodb-replica-set/gradle.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/gradle.yml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/silaev/mongodb-replica-set/gradle.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile.run-it-test-mongodb-replica-set:1: pin your Docker image by updating bellsoft/liberica-openjdk-alpine:8 to bellsoft/liberica-openjdk-alpine:8@sha256:45805740ebf12fcb6296b2d6bf2b94382d9856151af6b304f2daa039c23837d9","Warn: downloadThenRun not pinned by hash: scripts/codecov.sh:7","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned","Info:   0 out of   1 downloadThenRun dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 12 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T16:08:36.808Z","repository_id":44996986,"created_at":"2025-08-23T16:08:36.809Z","updated_at":"2025-08-23T16:08:36.809Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408828,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","java","mongodb","replica-set","testcontainers","transaction"],"created_at":"2026-01-14T03:22:51.487Z","updated_at":"2026-01-14T03:22:52.185Z","avatar_url":"https://github.com/silaev.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Run MongoDB Atlas locally for testing   \n![build](https://github.com/silaev/mongodb-replica-set/workflows/build/badge.svg?branch=master)\n[![codecov](https://codecov.io/gh/silaev/mongodb-replica-set/branch/master/graph/badge.svg)](https://codecov.io/gh/silaev/mongodb-replica-set)\n\n#### Prerequisite\n- Java 8+\n- Docker\n- Chart shows local and remote docker support for replicaSetNumber\n\n    replicaSetNumber | local docker host | local docker host running tests from inside a container with mapping the Docker socket | remote docker daemon | availability of an arbiter node |\n    :---: | :---: |:---: | :---: | :---: |\n    1 | + | + | + | - |\n    from 2 to 7 (including)  | only if adding either `host.docker.internal` (your Docker version should support it) or `dockerhost` to the OS host file. See \u003cb\u003eSupported features\u003c/b\u003e for details | + | + | + |\n\nTip:\nA single node replica set is the fastest among others. That  is the default mode for MongoDbReplicaSet.\nHowever, to use only it, consider the [Testcontainers MongoDB module on GitHub](https://www.testcontainers.org/modules/databases/mongodb/)\n    \n#### Getting it\n- Gradle:\n```groovy\ndependencies {\n    testCompile(\"com.github.silaev:mongodb-replica-set:${LATEST_RELEASE}\")\n}\n ```\n- Maven:\n```xml\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.github.silaev\u003c/groupId\u003e\n        \u003cartifactId\u003emongodb-replica-set\u003c/artifactId\u003e\n        \u003cversion\u003e${LATEST_RELEASE}\u003c/version\u003e\n        \u003cscope\u003etest\u003c/scope\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\nReplace ${LATEST_RELEASE} with [the Latest Version Number](https://search.maven.org/search?q=g:com.github.silaev%20AND%20a:mongodb-replica-set) \nIf you cannot find a release on Maven, please, use Jitpack\n\n#### Run on Apple silicon\nUse digests for linux/arm64/v8 and Docker Desktop for Apple silicon supporting host.docker.internal (should be in the OS host file).\nExamples:\n1.\n```\nMongoDbReplicaSet.builder()\n    .mongoDockerImageName(\"mongo@sha256:8a823923d80e819e21ee6c179eabf42460b6b7d8ac3dd5f35b59419ae5413640\")\n    .useHostDockerInternal(true)\n    .build()`\n```    \n2\n`./gradlew clean build -DmongoReplicaSetProperties.mongoDockerImageName=mongo@sha256:8a823923d80e819e21ee6c179eabf42460b6b7d8ac3dd5f35b59419ae5413640 -DmongoReplicaSetProperties.useHostDockerInternal=true`\n\n\n#### MongoDB versions that MongoDbReplicaSet is constantly tested against\nversion | transaction support |\n---------- | ---------- |\n3.6.14 |-|\n4.0.12 |+|\n4.2.8 |+|\n4.4.4 |+|\n5.0.5 |+|\n\n#### Examples\n\u003cdetails\u003e\n  \u003csummary\u003eClick to see a single node example\u003c/summary\u003e\n\n```java\nclass ITTest {\n    @Test\n    void testDefaultSingleNode() {\n        try (\n            //create a single node mongoDbReplicaSet and auto-close it afterwards\n            final MongoDbReplicaSet mongoDbReplicaSet = MongoDbReplicaSet.builder()\n                .mongoDockerImageName(\"mongo:4.4.4\")\n                .build()\n        ) {\n            //start it\n            mongoDbReplicaSet.start();\n            assertThat(\n                mongoDbReplicaSet.nodeStates(mongoDbReplicaSet.getMongoRsStatus().getMembers()),\n                hasItem(ReplicaSetMemberState.PRIMARY)\n            );\n            assertNotNull(mongoDbReplicaSet.getReplicaSetUrl());\n        }\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to see a fault tolerance example\u003c/summary\u003e\n\n```java\nclass ITTest {\n    @Test\n    void testFaultTolerance() {\n        try (\n            //create a PSA mongoDbReplicaSet and auto-close it afterwards\n            final MongoDbReplicaSet mongoDbReplicaSet = MongoDbReplicaSet.builder()\n                //with the latest mongo:4.4.4 docker image\n                .mongoDockerImageName(\"mongo:4.4.4\")\n                //If true then use host.docker.internal of Docker, \n                //otherwise take dockerhost of Qoomon docker-host.\n                //Make sure that your OS host file includes one of them.\n                //All new Docker versions support the first variant.\n                .useHostDockerInternal(true)\n                //with 2 working nodes\n                .replicaSetNumber(2)\n                //with an arbiter node\n                .addArbiter(true)\n                //create a proxy for each node to simulate network partitioning\n                .addToxiproxy(true)\n                .build()\n        ) {\n            //start it\n            mongoDbReplicaSet.start();\n            assertNotNull(mongoDbReplicaSet.getReplicaSetUrl());\n\n            //get a primary node\n            final MongoNode masterNode = mongoDbReplicaSet.getMasterMongoNode(\n                mongoDbReplicaSet.getMongoRsStatus().getMembers()\n            );\n\n            //cut off the primary node from network\n            mongoDbReplicaSet.disconnectNodeFromNetwork(masterNode);\n            //wait until a new primary is elected that is different from the masterNode\n            mongoDbReplicaSet.waitForMasterReelection(masterNode);\n            assertThat(\n                mongoDbReplicaSet.nodeStates(mongoDbReplicaSet.getMongoRsStatus().getMembers()),\n                hasItems(\n                    ReplicaSetMemberState.PRIMARY,\n                    ReplicaSetMemberState.ARBITER\n                )\n            );\n\n            //bring back the disconnected masterNode\n            mongoDbReplicaSet.connectNodeToNetwork(masterNode);\n            //wait until all nodes are up and running\n            mongoDbReplicaSet.waitForAllMongoNodesUp();\n            assertThat(\n                mongoDbReplicaSet.nodeStates(mongoDbReplicaSet.getMongoRsStatus().getMembers()),\n                hasItems(\n                    ReplicaSetMemberState.PRIMARY,\n                    ReplicaSetMemberState.ARBITER,\n                    ReplicaSetMemberState.SECONDARY\n                )\n            );\n        }\n    }\n}\n```\n\u003c/details\u003e\n \n- See more examples in the test sources [mongodb-replica-set on github](https://github.com/silaev/mongodb-replica-set/tree/master/src/test/java/com/github/silaev/mongodb/replicaset/integration)\n- See a full Spring Boot + Spring Data example [wms on github](https://github.com/silaev/wms/blob/master/src/test/java/com/silaev/wms/integration/ProductControllerITTest.java/)\n\n#### Motivation\n- Cross-platform solution that doesn't depend on fixed ports;\n- Testing MongoDB transactions to run against an environment close to a production one;\n- Testing production issues by recreating a real MongoDB replica set (currently without shards);\n- Education to newcomers to the MongoDB world (learning the behaviour of a distributed NoSQL database while \ndealing with network partitioning, analyze the election process and so on).\n   \n#### General info\n\u003cdetails\u003e\n  \u003csummary\u003eClick to see how to create a 3 node replica set on fixed ports via Docker manually\u003c/summary\u003e\n\nMongoDB starting from version 4 supports multi-document transactions only on a replica set.\nFor example, to initialize a 3 node replica set on fixed ports via Docker, one has to do the following:\n1. Add `127.0.0.1 mongo1 mongo2 mongo3` to the host file of an operation system;\n2. Run in terminal:\n    - `docker network create mongo-cluster`\n    - `docker run --name mongo1 -d --net mongo-cluster -p 50001:50001 mongo:4.0.10 mongod --replSet docker-rs --port 50001`\n    - `docker run --name mongo2 -d --net mongo-cluster -p 50002:50002 mongo:4.0.10 mongod --replSet docker-rs --port 50002`\n    - `docker run --name mongo3 -d --net mongo-cluster -p 50003:50003 mongo:4.0.10 mongod --replSet docker-rs --port 50003`\n3. Prepare the following unix end of lines script (optionally  put it folder scripts or use rs.add on each node):\n    ```js \n    rs.initiate({\n        \"_id\": \"docker-rs\",\n        \"members\": [\n            {\"_id\": 0, \"host\": \"mongo1:50001\"},\n            {\"_id\": 1, \"host\": \"mongo2:50002\"},\n            {\"_id\": 2, \"host\": \"mongo3:50003\"}\n        ]\n    });\n    ```\n4. Run in terminal:\n    - `docker cp scripts/ mongo1:/scripts/`\n    - `docker exec -it mongo1  /bin/sh -c \"mongo --port 50001 \u003c /scripts/init.js\"`\n\nAs we can see, there is a lot of operations to execute and we even didn't touch a non-fixed port approach.\nThat's where the MongoDbReplicaSet might come in handy. \n\u003c/details\u003e\n\n#### Supported features \nFeature | Description | default value | how to set | \n---------- | ----------- | ----------- | ----------- |\nreplicaSetNumber | The number of voting nodes in a replica set including a master one | 1 | MongoDbReplicaSet.builder() |\nawaitNodeInitAttempts | The number of approximate seconds to wait for a master or an arbiter node(if addArbiter=true) | 29 starting from 0 | MongoDBReplicaSet.builder() | \npropertyFileName | yml file located on the classpath | none | MongoDbReplicaSet.builder() |\nmongoDockerImageName | a MongoDB docker file name | mongo:4.0.10 | finds first set:\u003cbr/\u003e1) MongoDbReplicaSet.builder()\u003cbr/\u003e 2) the system property mongoReplicaSetProperties.mongoDockerImageName\u003cbr/\u003e 3) propertyFile\u003cbr/\u003e 4) default value | \naddArbiter | whether or not to add an arbiter node to a cluster | false | MongoDbReplicaSet.builder() |\nslaveDelayTimeout | whether or not to create one master and the others as delayed members | false | MongoDbReplicaSet.builder() |\nuseHostDockerInternal | If true then use `host.docker.internal` of Docker, otherwise take `dockerhost` of Qoomon docker-host | false | finds first set:\u003cbr/\u003e1) MongoDbReplicaSet.builder()\u003cbr/\u003e 2) the system property mongoReplicaSetProperties.useHostDockerInternal\u003cbr/\u003e 3) default value|\naddToxiproxy | whether or not to create a proxy for each MongoDB node via Toxiproxy | false | MongoDbReplicaSet.builder() |\nenabled | whether or not MongoReplicaSet is enabled even if instantiated in a test | true | finds first set:\u003cbr/\u003e1) the system property mongoReplicaSetProperties.enabled\u003cbr/\u003e2) propertyFile\u003cbr/\u003e3) default value |\ncommandLineOptions | command line options, example:`Arrays.asList(\"--oplogSize\", \"50\")` | emptyList | MongoDbReplicaSet.builder() |\n\na propertyFile.yml example: \n```yaml\nmongoReplicaSetProperties:\n  enabled: false\n  mongoDockerImageName: mongo:4.1.13\n```\n\n#### License\n[Apache License, Version 2.0](https://github.com/silaev/mongodb-replica-set/blob/master/LICENSE/)\n\n#### Additional links\n* [mongo-replica-set-behind-firewall](https://serverfault.com/questions/815955/mongo-replica-set-behind-firewall)\n* [Support different networks](https://jira.mongodb.org/browse/SERVER-1889)\n\n#### Copyright\nCopyright (c) 2022 Konstantin Silaev \u003csilaev256@gmail.com\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilaev%2Fmongodb-replica-set","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsilaev%2Fmongodb-replica-set","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilaev%2Fmongodb-replica-set/lists"}