How to enable authentication on MongoDB through Docker?
I want to spin-up a docker for mongodb:latest
but allow only certain user(s) to access certain db(s) (i.e. enable --auth
). No one else should access mongodb whatsoever! How should I do this as part of the docker initiation?
BTW, data directory
sits on the host by utilising the following command during initiation: -v /my/own/datadir:/data/db
.
Solution 1:
If you take a look at:
- https://github.com/docker-library/mongo/blob/master/4.2/Dockerfile
- https://github.com/docker-library/mongo/blob/master/4.2/docker-entrypoint.sh#L303-L313
you will notice that there are two variables used in the docker-entrypoint.sh
:
- MONGO_INITDB_ROOT_USERNAME
- MONGO_INITDB_ROOT_PASSWORD
You can use them to setup root user. For example you can use following docker-compose.yml
file:
mongo-container:
image: mongo:3.4.2
environment:
# provide your credentials here
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=rootPassXXX
ports:
- "27017:27017"
volumes:
# if you wish to setup additional user accounts specific per DB or with different roles you can use following entry point
- "$PWD/mongo-entrypoint/:/docker-entrypoint-initdb.d/"
# no --auth is needed here as presence of username and password add this option automatically
command: mongod
Now when starting the container by docker-compose up
you should notice following entries:
...
I CONTROL [initandlisten] options: { net: { bindIp: "127.0.0.1" }, processManagement: { fork: true }, security: { authorization: "enabled" }, systemLog: { destination: "file", path: "/proc/1/fd/1" } }
...
I ACCESS [conn1] note: no users configured in admin.system.users, allowing localhost access
...
Successfully added user: {
"user" : "root",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
To add custom users apart of root use the entrypoint exectuable script (placed under $PWD/mongo-entrypoint dir as it is mounted in docker-compose
to entrypoint):
#!/usr/bin/env bash
echo "Creating mongo users..."
mongo admin --host localhost -u USER_PREVIOUSLY_DEFINED -p PASS_YOU_PREVIOUSLY_DEFINED --eval "db.createUser({user: 'ANOTHER_USER', pwd: 'PASS', roles: [{role: 'readWrite', db: 'xxx'}]}); db.createUser({user: 'admin', pwd: 'PASS', roles: [{role: 'userAdminAnyDatabase', db: 'admin'}]});"
echo "Mongo users created."
Entrypoint script will be executed and additional users will be created.
Solution 2:
a. You can use environment variables via terminal:
$ docker run -d --name container_name \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=password \
mongo
If you like to test if everything works:
// ssh into the running container
// Change container name if necessary
$ docker exec -it mongo /bin/bash
// Enter into mongo shell
$ mongo
// Caret will change when you enter successfully
// Switch to admin database
$> use admin
$> db.auth("admin", passwordPrompt())
// Show available databases
$> show dbs
If you like to instantiate a database on first run, check option b.
b. You can use environment variables in your docker stack deploy file or compose file for versions 3.4 through 4.1.
As it is explained on the quick reference section of the official mongo image set MONGO_INITDB_ROOT_USERNAME
and MONGO_INITDB_ROOT_PASSWORD
in your yaml file:
mongo:
image: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: password
docker-entrypoint.sh file in mongo image checks for the existence of these two variables and sets --auth
flag accordingly.
c. You can also use docker secrets.
MONGO_INITDB_ROOT_USERNAME
and MONGO_INITDB_ROOT_PASSWORD
is set indirectly by docker-entrypoint.sh from MONGO_INITDB_ROOT_USERNAME_FILE
and MONGO_INITDB_ROOT_PASSWORD_FILE
variables:
mongo:
image: mongo
environment:
- MONGO_INITDB_ROOT_USERNAME_FILE=/run/secrets/db_root_username
- MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/db_root_password
secrets:
- db_root_username
- db_root_password
docker-entrypoint.sh converts MONGO_INITDB_ROOT_USERNAME_FILE
and MONGO_INITDB_ROOT_PASSWORD_FILE
to MONGO_INITDB_ROOT_USERNAME
and MONGO_INITDB_ROOT_PASSWORD
.
You can use MONGO_INITDB_ROOT_USERNAME
and MONGO_INITDB_ROOT_PASSWORD
in your .sh
or .js
scripts in docker-entrypoint-initdb.d
folder while initializing database instance.
When a container is started for the first time it will execute files with extensions .sh
and .js
that are found in /docker-entrypoint-initdb.d
. Files will be executed in alphabetical order. .js
files will be executed by mongo using the database specified by the MONGO_INITDB_DATABASE
variable, if it is present, or test otherwise. You may also switch databases within the .js
script.
This last method is not in the reference docs, so it may not survive an update.
Solution 3:
Better solutions for furthering:
https://blog.madisonhub.org/setting-up-a-mongodb-server-with-auth-on-docker/ https://docs.mongodb.com/v2.6/tutorial/add-user-administrator/
Here's what I did for the same problem, and it worked.
-
Run the mongo docker instance on your server
docker run -d -p 27017:27017 -v ~/dataMongo:/data/db mongo
-
Open bash on the running docker instance.
docker ps
CONTAINER IDIMAGE COMMAND CREATED STATUS PORTS NAMES
b07599e429fb mongo "docker-entrypoint..." 35 minutes ago Up 35 minutes 0.0.0.0:27017->27017/tcp musing_stallman
docker exec -it b07599e429fb bash root@b07599e429fb:/#
Reference- https://github.com/arunoda/meteor-up-legacy/wiki/Accessing-the-running-Mongodb-docker-container-from-command-line-on-EC2
-
Enter the mongo shell by typing mongo.
root@b07599e429fb:/# mongo
-
For this example, I will set up a user named ian and give that user read & write access to the cool_db database.
> use cool_db > db.createUser({ user: 'ian', pwd: 'secretPassword', roles: [{ role: 'readWrite', db:'cool_db'}] })
Reference: https://ianlondon.github.io/blog/mongodb-auth/ (First point only)
Exit from mongod shell and bash.
-
Stop the docker instance using the below command.
docker stop mongo
-
Now run the mongo docker with auth enabled.
docker run -d -p 27017:27017 -v ~/dataMongo:/data/db mongo mongod --auth
Reference: How to enable authentication on MongoDB through Docker? (Usman Ismail's answer to this question)
-
I was able to connect to the instance running on a Google Cloud server from my local windows laptop using the below command.
mongo <ip>:27017/cool_db -u ian -p secretPassword
Reference: how can I connect to a remote mongo server from Mac OS terminal
Solution 4:
I have hard time when trying to
- Create other db than admin
- Add new users and enable authentication to the db above
So I made 2021 answer here
My directory looks like this
├── docker-compose.yml
└── mongo-entrypoint
└── entrypoint.js
My docker-compose.yml
looks like this
version: '3.4'
services:
mongo-container:
# If you need to connect to your db from outside this container
network_mode: host
image: mongo:4.2
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=pass
ports:
- "27017:27017"
volumes:
- "$PWD/mongo-entrypoint/:/docker-entrypoint-initdb.d/"
command: mongod
Please change admin
and pass
with your need.
Inside mongo-entrypoint
, I have entrypoint.js
file with this content:
var db = connect("mongodb://admin:pass@localhost:27017/admin");
db = db.getSiblingDB('new_db'); // we can not use "use" statement here to switch db
db.createUser(
{
user: "user",
pwd: "pass",
roles: [ { role: "readWrite", db: "new_db"} ],
passwordDigestor: "server",
}
)
Here again you need to change admin:pass
to your root mongo credentials in your docker-compose.yml
that you stated before. In additional you need to change new_db
, user
, pass
to your new database name and credentials that you need.
Now you can:
docker-compose up -d
And connect to this db from localhost, please note that I already have mongo cli, you can install it or you can exec to the container above to use mongo
command:
mongo new_db -u user -p pass
Or you can connect from other computer
mongo host:27017/new_db -u user -p pass
My git repository: https://github.com/sexydevops/docker-compose-mongo
Hope it can help someone, I lost my afternoon for this ;)
Solution 5:
Just dropping a .js file into the entry point init folder works for this
e.g. entrypoint.js
var db = connect("mongodb://localhost/admin");
db.createUser(
{
user: "yourAdminUserName",
pwd: "yourAdminPassword",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)
docker-compose.yml:
db:
image: mongo:3.2
volumes:
- /my/own/datadir:/data/db
- ../mongo-entrypoint:/docker-entrypoint-initdb.d
Doing the rest by hand or more of the same works.
If you want to you can also drop a .sh file into the init folder to clean up the files so they are not laying around: zz-cleanup.sh.