-
Notifications
You must be signed in to change notification settings - Fork 620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot configure replica sets with entrypoint-initdb #339
Comments
|
Hmm - I did miss the "my hurried dockerfile will not actually work" point sorry! Still I think the idea has merit; but-for the squelching of the If there's a direction you think would be acceptable and could be made to work I'd be willing to have a go at implementing it. |
According to https://docs.mongodb.com/manual/reference/method/rs.initiate/,
"rs.initiate" can accept a "configuration" argument -- is it possible
to provide the hosts list as part of that block, or does "rs.initiate"
choke on that?
(Worst case you could "rs.reconfig" after your "rs.initiate" to
provide the values you want:
https://docs.mongodb.com/manual/reference/method/rs.reconfig/)
|
@tianon - both |
The So you'll probably need some manual intervention after everything is initialized, as using the |
I have the same issue. Was this ever solved? |
Somehow, I wrote an ugly hack to initialize replica set by abusing docker-entrypoint-initdb.d. Hope that helps someone coming to this issue. |
@esetnik - It's kinda hard to fix since Mongodb will sanity check any attempt to configure a replicaset and reject it if it looks invalid. To fix there there would have to be some 'force' option on replicasets within mongo or similar. I'd argue there's a case for this but it's probably not top of anyone's list. In the end I wrote a sibling docker container that loops waiting for the mongodb to be available externally, configures the replicaset, then shuts down (though for non-test scopes I guess it could forever listen and set the replicasets). A better person might use consul or etcd or similar to co-ordinate all this. @zhangyoufu's solution is terrible and beautiful at the same time! :D |
What a hack @zhangyoufu! I think there needs to be some support for this in the official docker image. There are several features of MongoDB only available with a replica set and this is a common production configuration. So it makes local development hard if we cannot setup a dev db with the same configuration. |
I think that To keep this mongod instance "private" (do not serve) while initdb is in progress, and circumvent the check inside But modifying |
Thank you @zhangyoufu for the hack. It worked (with minor tweaks to be able to handle authentication as well). It felt a bit too 'hacky' for me though as I don't like abusing or modifying the original entrypoint script behavior. So I did a small workaround with a custom entrypoint that just calls the original one and after that is concluded executes the
It is also very hacky, but I think will cope better with updates of the original entrypoint script. Also the code is just some quick first solution, so be aware it might be buggy. But maybe it might be helpful to someone running into the same issue. |
Maybe this can be helpful too https://gist.github.com/zhangyoufu/d1d43ac0fa268cda4dd2dfe55a8c834e#gistcomment-3554586 |
Hi Everyone, We have come across the same issue when trying to initialize a replica set using JS script within the entry point. Was this issue closed with a solution? If so, I would greatly appreciate it if you could point me to it. |
I was able to do it from this gist: https://gist.github.com/zhangyoufu/d1d43ac0fa268cda4dd2dfe55a8c834e I added my full setup as a comment as well |
I'v come up a work-around using Define a js script to detect master status, then do init once if necessary: init = false;
if (!db.isMaster().ismaster) {
print("Error: primary not ready, initialize ...")
rs.initiate();
quit(1);
} else {
if (!init) {
admin = db.getSiblingDB("admin");
admin.createUser(
{
user: "test",
pwd: "pass",
roles: ["readWriteAnyDatabase"]
}
);
init = true;
}
} In docker-compose, define a healthcheck using the script: mongodb:
image: mongo:4.0
environment:
- AUTH=no # without password
tmpfs: /data/db
hostname: mongodb
volumes:
- "./volume/mongo-init2.js:/mongo-init.js"
command: [mongod, --replSet, 'rs2', --noauth, --maxConns, "10000"]
healthcheck:
test: mongo /mongo-init.js
interval: 5s Though this requires further version: "3.9"
...
services:
...
depends_on:
mongodb:
# requires compose version prior 3.0, or 3.9+, but not between
# see https://stackoverflow.com/a/41854997/108112
condition: service_healthy |
Given the current life cycle in which said |
In order to properly do that (run processes after starting the "real" long-term By supervisor process, I mean basically the following:
You don't have to deal with the first 6 if the container is used as-is since that is "free" because of how the image is designed. And then the correct solution is to use your orchestration platform to run something to coordinate the initialization and joining of multiple
|
@wglambert can this be made consisten with mongodb behavious outside of the docker? In my case I do have need to initialize replica set of 1 node |
Alright, I already read https://github.com/docker-library/mongo/blob/master/docker-entrypoint.sh and it appears that only valid case for rs initiation will be mine, no good way to make replica set working with other hardcoded arguments. Can this be properly documented on docker mongodb page? As this was really confusing and time consuming to dig through. |
For anyone looking for an answer to this in a Compose stack, you can set the |
For anyone looking to the answer, here is a hack that made it working for me. I've made a #!/bin/bash
# Initialize MongoDB server as a replica set and seed the database
# NOTE: This is a workaround since initializing the MongoDB server as
# a replica set cannot be done in the script placed in the
# /docker-entrypoint-initdb.d/ directory.
if ! mongosh --quiet --eval "rs.status().ok" &> /dev/null; then
echo "Replica set not initialized, attempting to initiate..."
if ! mongosh --quiet --eval "rs.initiate()"; then
echo "Failed to initiate replica set"
exit 1
else
echo "Replica set initiated successfully."
mongosh /mongodb/seed.js || echo "Failed to seed the database"
fi
else
echo "Replica set is already initialized."
fi
# Final health check
if ! mongosh --quiet --eval "rs.status().ok" &> /dev/null; then
echo "Health check failed: Replica set is not ok."
exit 1
else
echo "Health check passed: Replica set is ok."
fi and calling that mongodb:
image: mongo:7
container_name: mongodb
ports:
- "27017:27017"
volumes:
- mongodb_data:/data/db
- ../db/mongodb/seed/seed.js:/mongodb/seed.js
- ../db/mongodb/healthcheck.sh:/mongodb/healthcheck.sh
networks:
- atlas_net
environment:
- MONGO_INITDB_DATABASE=atlas
- MONGO_REPLICA_SET_NAME=rs0
command: --replSet rs0 --bind_ip_all --port 27017
healthcheck:
test: /mongodb/healthcheck.sh
interval: 15s
timeout: 10s
retries: 3
start_period: 20s
restart: always |
I'm trying to create simple replicaset enabled images using these docker images. @yosifkit had a suggestion in another thread that this can be done by calling
rs.initiate()
in a/docker-entrypoint-initdb.d/
script.However if I do this I get the following:
The problem here is that since the init script binds only to localhost, the replicaset has the wrong hostname.
If I call
rs.initiate()
after initialization phase I get the following:This time with the correct hostname.
Is there some way we can resolve this paradox? Either by running a script after the real startup? Or by binding to the proper interfaces during initialisation? Or by forcing the mongo server to accept a replicaset config even if it cannot resolve itself?
Thanks!
The text was updated successfully, but these errors were encountered: