I want to create a MongoDB replica set with a standalone instance running in docker to be able to work with multi-document transactions.
The problem is that the replica set is not initiated automatically, I always have to start it manually, so I can't run it in gitlab runner.
My Dockerfile is as follows:
FROM mongo:4.2
RUN echo "rs.initiate({'_id':'rs0','members':[{'_id':0,'host':'127.0.0.1:27017'}]});" > /docker-entrypoint-initdb.d/replica-init.js
RUN chmod u+x /docker-entrypoint-initdb.d/replica-init.js
RUN cat /docker-entrypoint-initdb.d/replica-init.js
CMD [ "--bind_ip_all", "--replSet", "rs0" ]
And here the docker-compose snippet:
mongo:
build:
context: .
dockerfile: docker/mongo/Dockerfile
command: --replSet rs0
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
ports:
- 27017:27017
I put this script into docker-entrypoint-initdb.d so it should run automatically on first container start but it does not happen.
If I run the same initiate() command manually using mongo shell - it then works fine.
Any ideas on what I do wrong?
Related
Following the steps mentioned in the official docs in Docker Hub for Mongo.
I am able to build everything as expected by first pulling the relevant images and then running docker-compose up command against following file.
It starts up without issues and also able to open the shell via the command below.
But in that shell, running something like show dbs which is a Mongo command is not recognized.
Am I missing any further setups for this? Please advice. Thank you.
My docker-compose.yml file
version: "3.1"
services:
mongo:
image: mongo
container_name: mongo-instance-1
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
volumes:
- ./data:/data/db
mongo-express:
image: mongo-express
container_name: mongo-express-instance-1
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: example
I then open the shell via following command which opens the bash terminal.
docker exec -it mongo-instance-1 bash
But Mongo commands not recognized in there as follows.
Ran following command
show dbs
Error output
bash: show: command not found
mongo has been renamed to mongosh - this works for me
docker exec -it mongo-instance-1 mongosh
You are in bash at this stage.
You need to enter mongo via following command.
mongo admin -u root -p example
Now try running your show dbs command which will work. Good luck.
show dbs
You need to run the mongo client from the container instead of the bash shell:
docker exec -it mongo-instance-1 mongo
And then the commands ...
I'm using docker-compose version 1.25.5, build 8a1c60f6 &
Docker version 19.03.8, build afacb8b
I'm trying to initialise database with Users in MongoDb container using docker-entrypoint-initdb.d but,
js/scripts aren't being executed when container starts.
I know /data/db must be empty for it execute so I've been deleting it every time before start. But still doesn't execute. Going into the container and manually executing mongo mongo-init.js works.
Not sure why it's not working when it should.
docker-compose.yml:
version: '3'
services:
mongodb:
container_name: "mongodb"
image: tonyh308/cv-mongodb:1
build: ./mongo
container_name: mongodb
restart: always
ports:
- 27017:27017
environment:
MONGO_INITDB_DATABASE: test
volumes:
- ./docker-entrypoint-initdb.d/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
- ./mongo/mongodb:/data/db
labels:
com.qa.description: "MongoDb Container for application."
# other services ...
Dockerfile:
FROM mongo:3.6.18-xenial
RUN apt-get update
COPY ./Customers /Customers
COPY ./test /test
WORKDIR /data
ENTRYPOINT ["mongod", "--bind_ip_all"]
EXPOSE 27017
Feb 26 2021: still no solution
This is my Dockerfile:
FROM mongo
WORKDIR /usr/src/app
COPY db /usr/src/app/db
COPY replica.js /usr/src/app/
CMD mongo
The replica.js as follows
rs.initiate();
This is my docker-compose file
mongo_server:
image: mongo
hostname: mongo_server.$ENV_NAME
build:
context: ./mongo
dockerfile: Dockerfile
expose:
- 27017
ports:
- "$MONGO_PORT:27017"
restart: always
networks:
localnet:
aliases:
- mongo_server.$ENV_NAME
command: --replSet $MONGO_REPLICA --bind_ip_all
volumes:
- "mongovolume:/data/db"
The problem is if I run successfully docker-compose up.
Then I need to run manually two command
docker exec 2b2 sh -c "mongo < /usr/src/app/replica.js" # 2b2 is id of container mongo
and
docker exec 2b2 sh -c "mongorestore --drop -d mydb /usr/src/app/db"
Now the replica is set, the database is restored. My question is could I make it automatically such as moving to entrypoint.sh and call in Dockerfile or setting in docker-compose.yml to reduce manual work?
There is definitely a way by adding another container in your docker-compose file:
mongo_restore:
image: mongo
build:
context: ./mongo
dockerfile: Dockerfile
networks:
localnet:
aliases:
- mongo_server.$ENV_NAME
entrypoint:
- sh
command:
- -c
- |
# Step 1: Wait until mongo_server is fully up and running. Please insert your own code to check.
# Step 2: Execute your restore script but make sure to target mongo_server instead
volumes:
- "mongovolume:/data/db"
There might be some syntax errors here and there but the idea is the same as I have used this method in some other projects :)
Current State
I have a MongoDB instance running on a server without the replication set flag (--replSet)
I have some previously stored information on the Database and wish to retain the information
Aim
I wish to however restart the container with the --replSet "my-set" flag set for the daemon and keep the previous information intact
Implementation
I am trying to follow along a tutorial for setting replica sets in MongoDB with Docker and trying it out on my local machine.
Create a standard MongoDB Docker container w/o the flag replSet set which represents the current state:
docker run -d --name mongo_rs --publish 37017:27017 mongo
Using the MongoDB Compass I connected to the DB and added some dummy information to a Database called test and collection called players
I stop the container:
docker container stop mongo_rs
From here onwards I wish to add the --replSet "my-set" to the mongo_rs container and configuring the Replica set via the mongo Shell as mentioned in the tutorial. What is the possible solution for achieving it?
Here is my .yml file
version: '3.7'
services:
node1:
image: mongo
ports:
- 30001:27017
volumes:
- $HOME/mongoclusterdata/node1:/data/db
networks:
- mongocluster
command: mongod --replSet comments
node2:
image: mongo
ports:
- 30002:27017
volumes:
- $HOME/mongoclusterdata/node2:/data/db
networks:
- mongocluster
command: mongod --replSet comments
depends_on :
- node1
node3:
image: mongo
ports:
- 30003:27017
volumes:
- $HOME/mongoclusterdata/node3:/data/db
networks:
- mongocluster
command: mongod --replSet comments
depends_on :
- node2
networks:
mongocluster:
driver: bridge
The volume section has absolute path which is different from the root.Actually docker file creates a self config file on root , so if u have root as a docker-compose install location change it to else where, and now the config file settings would never delete on docker-install up/down.
Here is a workaround:
1- copy the entrypoint script to your host:
docker cp mongo_rs:/usr/local/bin/docker-entrypoint.sh .
2- edit the script , change the line (last line) exec "$#" to :
mongod --replSet my-mongo-set --port 27017
3- re-copy the script to your container:
docker cp docker-entrypoint.sh mongo_rs:/usr/local/bin/docker-entrypoint.sh
4- start your container:
docker start mongo_rs
Okay so I know I can automate my "docker run" instructions like this, say I would do this without compose:
First create the volume
docker volume create --name mongodb-shard-1-node-1
Then the container
docker run --name mongodb-node-1 -d -v mongodb-node-1:/data/db -p 27031:27017 --link mongo-node-2:mongo mongo --replSet rs0 --smallfiles --oplogSize 128
This would be the same as including this in the docker-compose.yml file:
mongodb-node-1:
image: mongo
volumes:
- "mongodb-node-1:/data/db"
ports:
- "27031:27017"
container_name: mongodb-node-1
external_links:
- "mongodb-node-3:mongo"
command: --replSet rs0 --smallfiles --oplogSize 128
But I also have to run commands inside the mongodb shell, to do this I first use exec to enter the shell like this:
docker exec -it mongodb-shard-1-node-1 mongo
afterwards inside the shell I need to run commands such as
rs.initiate()
and others like
rs.addArb("172.17.0.6:27017")
etc...
Can I automate these last steps with docker-compose? Is it possible to automate this in docker at all?
You can't directly automate it like that, sadly.
As a workaround, you could extend the container to add in a shell script which runs, starts Mongo, then runs the specified commands. You could even pass in that IP address in an environment variable if it needs to be modifiable.
Kontena has leveraged docker-compose.yml file format and introduced this kind of functionality by adding post_start hook.
peer:
image: mongo:3.2
stateful: true
command: --replSet kontena --smallfiles
instances: 3
hooks:
post_start:
- cmd: sleep 10
name: sleep
instances: 1
oneshot: true
- cmd: mongo --eval "printjson(rs.initiate());"
name: rs_initiate
instances: 1
oneshot: true
- cmd: mongo --eval "printjson(rs.add('%{project}-peer-2'))"
name: rs_add2
instances: 1
oneshot: true
- cmd: mongo --eval "printjson(rs.add('%{project}-peer-3'))"
name: rs_add3
instances: 1
oneshot: true
https://github.com/kontena/examples/blob/master/mongodb-cluster/kontena.yml
$ kontena app deploy command will deploy all three mongodb peers and add them to replica set.