I have a node back-end application which requires MongoDB with replica set. I have created a docker image for my application which simply runs the application; also created a docker-compose file which runs the MongoDB instance and config its replica set.
here is my docker-compose file:
version: '2'
services:
mongod1:
image: mongo
command: mongod --replSet ${RS} --oplogSize 16 --smallfiles --noprealloc --bind_ip 0.0.0.0
ports:
- '27017:27017'
mongod2:
image: mongo
command: mongod --replSet ${RS} --oplogSize 16 --smallfiles --noprealloc --bind_ip 0.0.0.0
ports:
- '27018:27017'
mongod3:
image: mongo
command: mongod --replSet ${RS} --oplogSize 16 --smallfiles --noprealloc --bind_ip 0.0.0.0
ports:
- '27019:27017'
mongo-config:
image: mongo
depends_on:
- mongod1
- mongod2
- mongod3
volumes:
- ./scripts:/scripts
environment:
- MONGO1=mongod1
- MONGO2=mongod2
- MONGO3=mongod3
- USER=machine
- PWD=abc123456
- RS=rs0
entrypoint: ['/scripts/setup.sh']
and in the entrypoint I have the bash script like below:
#!/bin/bash
mongodb1=$(getent hosts ${MONGO1} | awk '{ print $1 }')
mongodb2=$(getent hosts ${MONGO2} | awk '{ print $1 }')
mongodb3=$(getent hosts ${MONGO3} | awk '{ print $1 }')
port=${PORT:-27017}
echo "Waiting for startup.."
until mongo --host ${mongodb1}:${port} --eval 'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)' &>/dev/null; do
printf '.'
sleep 1
done
echo "Started.."
echo "setup.sh; time now: $(date +"%T")"
mongo --host ${mongodb1}:${port} <<EOF
use admin
db.createUser(
{
user: ${USER},
pwd: #{pwd},
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)
EOF
mongo --host ${mongodb1}:${port} <<EOF
var cfg = {
"_id": "${RS}",
"members": [
{
"_id": 0,
"host": "${mongodb1}:${port}"
},
{
"_id": 1,
"host": "${mongodb2}:${port}"
},
{
"_id": 2,
"host": "${mongodb3}:${port}"
}
]
};
rs.initiate(cfg, { force: true });
rs.config();
EOF
mongo --host ${mongodb2}:${port} <<EOF
db.setSlaveOk()
EOF
mongo --host ${mongodb3}:${port} <<EOF
db.setSlaveOk()
EOF
now im my envirement i can connect to mongodb in localhost:27017 but application cannot connect to 0.0.0.0:27017.
how I can fix this? should i use docker networks?
try to change 0.0.0.0 to 127.0.0.1 or just use localhost.
BTW, I cannot create auth from your method by keeping getting Error: couldn't add user: not master, so I searched around, and found out that before rs.initiate() has been called, and if a mongod.conf with a setting of replication.replSetName: rs existed, the mongo instance you are connecting to will have no idea who is master or Primary.
so I switched the order of createUser and rs.initiate(), and put a delay, then it works fine.
Thanks for the skeleton.
version: "3.3"
services:
mongo-admin:
image: mongo-express
container_name: "mongo-admin"
environment:
- ME_CONFIG_MONGODB_SERVER=db_manager,db_worker_1,db_worker_2
- ME_CONFIG_OPTIONS_EDITORTHEME=ambiance
- ME_CONFIG_BASICAUTH_USERNAME=$MONGOADMIN
- ME_CONFIG_BASICAUTH_PASSWORD=$MONGOPASS
ports:
- 8081:8081
restart: on-failure
depends_on:
- db_manager
- db_worker_1
- db_worker_2
- mongo-set-setup
db_manager:
image: mongo:4.0
container_name: db_manager
volumes:
- mongodb1:/data/db
- ./mongod.conf:/etc/mongod.conf
command: mongod --config /etc/mongod.conf
ports:
- "27017:27017"
restart: always
db_worker_1:
image: mongo:4.0
container_name: db_worker_1
volumes:
- mongodb2:/data/db
- ./mongod.conf:/etc/mongod.conf
command: mongod --config /etc/mongod.conf
ports:
- "27018:27017"
restart: always
db_worker_2:
image: mongo:4.0
container_name: db_worker_2
volumes:
- mongodb3:/data/db
- ./mongod.conf:/etc/mongod.conf
command: mongod --config /etc/mongod.conf
ports:
- "27019:27017"
restart: always
mongo-set-setup:
container_name: "mongo-set-setup"
image: mongo:4.0
depends_on:
- db_manager
- db_worker_1
- db_worker_2
volumes:
- ./setupmongo.sh:/scripts/setupmongo.sh
environment:
- MONGO1=db_manager
- MONGO2=db_worker_1
- MONGO3=db_worker_2
- USER=$MONGOUSER
- PASSWORD=$MONGOPASSWORD
- RS=rs
entrypoint: ["/scripts/setupmongo.sh"]
#
volumes:
mongodb1:
mongodb2:
mongodb3:
and shell
#!/bin/bash
mongodb1=`getent hosts ${MONGO1} | awk '{ print $1 }'`
mongodb2=`getent hosts ${MONGO2} | awk '{ print $1 }'`
mongodb3=`getent hosts ${MONGO3} | awk '{ print $1 }'`
port=${PORT:-27017}
echo "Waiting for startup.."
until mongo --host ${mongodb1}:${port} --eval 'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)' &>/dev/null; do
printf '.'
sleep 1
done
echo "Started.."
echo ~~~~~~~~setup replic time now: `date +"%T" `
echo ${mongodb1}, ${mongodb2}, ${mongodb3}
mongo --host ${mongodb1}:${port} <<EOF
var cfg = {
"_id": "${RS}",
"protocolVersion": 1,
"members": [
{
"_id": 0,
"host": "${mongodb1}:${port}",
"priority": 2
},
{
"_id": 1,
"host": "${mongodb2}:${port}",
"priority": 0
},
{
"_id": 2,
"host": "${mongodb3}:${port}",
"priority": 0
}
]
};
rs.initiate(cfg, { force: true });
rs.reconfig(cfg, { force: true });
rs.slaveOk();
db.getMongo().setReadPref('nearest');
db.getMongo().setSlaveOk();
EOF
sleep 30
echo ${USER}, ${PASSWORD}
echo ~~~~~~~~~~setup user auth time now: `date +"%T" `
mongo --host ${mongodb1}:${port} <<EOF
use admin
db.createUser(
{
"user": "${USER}",
"pwd": "${PASSWORD}",
"roles": [ "readWrite"]
}
)
EOF
Related
I always get this error trying to connect to the Mongodb
MongoDB Response
server selection error: server selection timeout, current topology: { Type: ReplicaSetN
oPrimary, Servers: [{ Addr: mongodb:27017, Type: Unknown, Last error: connection() error occured during connection handshake: dial tcp: lookup mongodb: no such host }, ] }
MongoDB Log
mongodb | 2022-03-08T06:40:26.387+0000 I NETWORK [conn14]
received client metadata from 172.25.0.1:39218 conn14: { driver: {
name: "mongo-go-driver", version: "v1.8.3" }, os: { type: "windows",
architecture: "amd64" }, platform: "go1.17.5" }
Here is how I set up
docker-compoes.yml
mongodb:
container_name: mongodb
build: ./mongo
ports:
- 27017:27017
environment:
- MONGODB_USER=debezium
- MONGODB_PASSWORD=dbz
networks:
- pg-es-synch_default
Dockerfile
FROM mongo:3.6
CMD ["mongod", "--replSet", "rs0", "--auth"]
Command
>> mongo localhost:27017/ecommerce_connect
rs.initiate({
_id: "rs0",
members: [ { _id: 0, host: "mongodb:27017" } ]
});
>> mongo localhost:27017/admin
db.createUser({ user: 'admin', pwd: 'admin', roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] });
>> mongo -u admin -p admin localhost:27017/admin
db.createUser({
user:
'debezium',
pwd: 'dbz',
roles: [
{ role: "readWrite", db: "ecommerce_connect" },
{ role: "readWrite", db: "local" },
{ role: "root", db: "admin" },
{ role: "readWrite", db: "config" },
]
});
When I login by user debezium outside Docker in the localhost I always got the error mentioned above.
But if I do this in CLI of Docker, It works
>> mongo -u debezium -p dbz --authenticationDatabase admin localhost:27017/ecommerce_connect
use ecommerce_connect;
db.product_info.insert([
{ _id : NumberLong("128"), name : 'scooter', description: 'Small 2-wheel scooter', weight : 3.14, quantity : NumberInt("3") }
]);
I connect to mongoDB by this URL:
"mongodb://debezium:dbz#localhost:27017"
I am trying to create a docker-compose file for MongoDB after checking out multiple examples on the web and this is my configuration. However after executing docker-compose up command, when trying to login using any of the below credentials in Compass at localhost:37017, I am getting the error:
UserNotFound: Could not file user "dbAdmin" for db "admin"
Folder structure
mongo [directory]
docker-entrypoint-initdb.d [directory]
mongo-init.js
mongo-volume [directory]
docker-compose.yml
docker-compose.yml content:
version: '3'
services:
mongoDB:
image: 'mongo:latest'
container_name: 'app-mongo'
environment:
- MONGO_INITDB_ROOT_USERNAME=dbAdmin
- MONGO_INITDB_ROOT_PASSWORD=TtUBhMjOIfeV
- MONGO_INITDB_DATABASE=admin
volumes:
- ./docker-entrypoint-initdb.d/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
- ./mongo-volume:/data/db
ports:
- '37017-37019:27017-27019'
mongo-init.js content
let admin = db.getSiblingDB("admin");
admin.createUser({
user : "appAdmin",
password: "TtUBhMjOIfeV",
db: "admin",
roles: [
{
role: "clusterAdmin",
db: "admin"
},
{
role: "userAdminAnyDatabase",
db: "admin"
}
]
});
admin.createCollection("users");
let adppDBName = db.getSiblingDB("appDBName");
appDBName.createUser({
user: "appOwner",
password: "EtMxw6ZY9jiG",
db: "admin",
roles: [
{
role: "readWrite",
db: "appDBName"
}
]
});
appDBName.createCollection("users");
You created a user named appAdmin but are apparently trying to use a user named dbAdmin.
I am using following docker-compose file
version: '3.7'
services:
db_container:
image: mongo:latest
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
MONGO_INITDB_DATABASE: root-db
ports:
- 27017:27017
volumes:
- ./database/initdb.js:/docker-entrypoint-initdb.d/initdb.js:ro
- ./data:/data/db
Here is my initdb.js file
db.createUser(
{
user: "api-test",
pwd: "api-test",
roles: [
{
role: "readWrite",
db: "api-test"
}
]
}
);
I can see only 3 databases and unable to connect to api-test DB
Please help me if something is missing
Able to solve the issue with the help of the following article
Docker-Compose mongoDB Prod, Dev, Test Environment
The file structure should be
Project
├── docker-compose.yml (File)
├── docker-entrypoint-initdb.d (Directory)
│ ├── mongo-init.js (File)
docker-compose.yml file
version: '3.7'
services:
mongo:
container_name: container-mongodb
image: mongo:latest
restart: always
ports:
- 27017:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
MONGO_INITDB_DATABASE: root-db
volumes:
- ./docker-entrypoint-initdb.d/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
mongo-init.js file
print('Start #################################################################');
db = db.getSiblingDB('api_prod_db');
db.createUser(
{
user: 'api_user',
pwd: 'api1234',
roles: [{ role: 'readWrite', db: 'api_prod_db' }],
},
);
db.createCollection('users');
db = db.getSiblingDB('api_dev_db');
db.createUser(
{
user: 'api_user',
pwd: 'api1234',
roles: [{ role: 'readWrite', db: 'api_dev_db' }],
},
);
db.createCollection('users');
db = db.getSiblingDB('api_test_db');
db.createUser(
{
user: 'api_user',
pwd: 'api1234',
roles: [{ role: 'readWrite', db: 'api_test_db' }],
},
);
db.createCollection('users');
print('END #################################################################');
Although my setup was correct, removed volumes, modified the db, etc, none of these worked for me.
The only way was to change the name of the mongodb container inside the docker-compose, instead of mongo I wrote mongodb and it worked.
everyone,
I'm having a hard time setting up a MongoDB container to have root password and creating a new user with less privileges (that will be my application user) automatically.
Ideally I should have only some scripts and a docker-compose configuration.
I tried adding the MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD but they don't seem to work. They do something, because when I start the container like that, I can't just connect to the mongo shell and run all the commands (and passing username and password will throw unauthorized errors).
Then I thought about adding a script at /docker-entrypoint-initdb.d/ but they dont seem to run. They don't show on console. Besides, i just put a javascript like this and I am not sure whether they will work:
var db = connect("mongodb://localhost/admin");
db.createRole(
{
role: "somerole",
privileges: [
{
actions: [ "find", "update", "insert" ],
resource: { db: "mydb", collection: "" } <--- does it means all colections od database mydb?!?!
}
],
roles: [ ]
}
)
db.createUser(
{
user: "admin",
pwd: "adminpass",
roles: [ { role: "userAdminAnyDatabase", db: "mydb" } ]
}
)
db.createUser(
{
user: "system",
pwd: "systempass",
roles: [ { role: "somerole", db: "mydb" } ]
}
)
I would also want to create collections and insert documents. How do we do that? Shouldn't it be with entrypoints!?
MongoDb Documentation: Security Reference
Partial response 1
Partial response 2
1) Create the following structure of files:
2) Content of docker-compose.yml
version: "3"
services:
mongodb:
image: "mongo:4.1.1-xenial"
restart: "unless-stopped"
env_file:
- ".env"
ports:
- "27017:27017"
volumes:
- "./database/data:/data/db" # Database files
- "./database/fixtures:/docker-entrypoint-initdb.d" # To create Db at start
3) Content of default.js
/* Create a New user with "only READ" role */
db = db.getSiblingDB('admin');
db.createUser(
{
"user": "John",
"pwd": "MyPassword",
"roles": [
{ "role": "read", "db": "data" }
]
})
/* Misc - Other Data */
db = db.getSiblingDB('data');
db.data.save([
{
"name": "Frank",
"email": "email1#gmail.com",
},
{
"name": "Peter",
"email": "email2#gmail.com",
}
]);
4) Content of .env
MONGO_INITDB_ROOT_USERNAME=Robert
MONGO_INITDB_ROOT_PASSWORD=GoodPassword
5) Go to your terminal and at the level of the docker-compose.yml file, execute:sudo docker-compose up -d
6) Get the container's name:
Execute: sudo docker ps a
7) Go inside the container:
Execute: sudo docker exec -it <CONTAINER NAME> bash
8) Inside the container:
Execute: mongo --host localhost -u Robert -p GoodPassword --authenticationDatabase admin
NOTE: Take into account that we are specifying the "authentication database"
9) Select database:
Execute: use admin
10) Show users (You must find two users Robert and John):
Execute: show users
As you can see inside "data" directory are stored the files of the database.
And using the default.js file you can create collections frm the start.
IMPORTANT NOTE: If you make some changes and those are not reflected to the database, then you need to DELETE the content of "data" and run again: docker-compose up -d
We can say that, if "data" directory is not empty, then the "default.js" file will not be taked into account.
I changed a bit your configuration and it runs correctly:
docker-compose.yml:
version: '3.1'
services:
mongo:
image: mongo
restart: always
volumes:
- ./init.js:/docker-entrypoint-initdb.d/init.js
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
MONGO_INITDB_DATABASE: mydb
here I specify the database to be created initially and I also mount the init script.
init.js:
var db = connect("mongodb://localhost/mydb");
db.createRole(
{
role: "somerole",
privileges: [
{
actions: [ "find", "update", "insert" ],
resource: { db: "mydb", collection: "" }
}
],
roles: [ ]
}
)
db.createUser(
{
user: "admin",
pwd: "adminpass",
roles: [ { role: "somerole", db: "mydb" } ]
}
)
db.createUser(
{
user: "system",
pwd: "systempass",
roles: [ { role: "somerole", db: "mydb" } ]
}
)
The important part here is the first line, otherwise you create a role in the admin database while you look for it in mydb database.
With this setup I can start the database and connect to it.
I am getting the following error message when trying to config my replica sets in MongoDb.
the config statement is as follows,
var demoConfig={ _id: "demo", members: [{ _id: 0, host: 'localhost: 30000', priority: 10}, { _id: 1, host: 'localhost: 40000'}, { _id: 2, host: 'localhost: 50000', arbiterOnly: true}] };
I have started 3 MongoDb instances using the following .bat commands. I am using MongoDB v.3.6 and running on Windows 7 desktop.
cd C:\demos\mongodb\mongoData
#REM Primary
start "a" mongod --dbpath ./data/db1 --port 30000 --replSet "demo"
#REM Secondary
start "b" mongod --dbpath ./data/db2 --port 40000 --replSet "demo"
#REM Arbiter
start "c" mongod --dbpath ./data/db3 --port 50000 --replSet "demo"
Why am I getting this error message ? I have tried replacing the ' with ` but it makes no difference I still get the same error.
I found the answer. I needed to remove the space between "localhost:" and the port address i.e. change from 'localhost: 30000' to 'localhost:30000'. So my corrected demoConfig becomes,
var demoConfig={ _id: "demo", members: [{ _id: 0, host: 'localhost:30000', priority: 10}, { _id: 1, host: 'localhost:40000'}, { _id: 2, host: 'localhost:50000', arbiterOnly: true}] };
and this worked for me.