This is mostly a "note to self" kind of thing as I keep having to look up how to run MongoDb with authentication enabled for local development.

The easy way is to specify two environment variables:

  • MONGO_INITDB_ROOT_USERNAME
  • MONGO_INITDB_ROOT_PASSWORD

However, this will give you the root user (clue is in the variable name, I suppose) which has a bit more access than you might want.

You might say: "But, why bother? It's all configured with authentication in the live environment anyway. Using this in local development is just a hassle."

The thousands of breaches of improperly configured exposed MongoDb instances aside, the idea is:

Always keep security as part of your development cycle - from the beginning

This means that there are no surprises when going into production. Also, it makes the transition easier as well - no special code for local vs production etc.

So, I would like a restricted user for my application when connecting to MongoDb running in Docker locally.

Turns out, there's a simple trick for this. MongoDb will run any scripts that are placed inside /docker-entrypoint-initdb.d.

Let's create a createusers.sh script:

#!/usr/bin/env bash
echo "Creating users..."
mongo admin --host localhost -u root -p root --eval "db.createUser({user: 'appuser', pwd: 'supersecret',roles: [{role: 'readWrite', db: 'MyAppDb'}]}); db.createUser({user: 'administrator', pwd: 'no1willguess', roles: [{role: 'userAdminAnyDatabase', db: 'admin'}]});"
echo "Users created."

We can place this script in a folder (lets call it mongo-scripts) that we will volume mount into the Docker container.
Also, we need to start MongoDb with authentication enabled to be able to authenticate.

docker run --name mongo -p 27017:27017 --rm -it -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=root -v `pwd`/mongo-scripts/:/docker-entrypoint-initdb.d/ mongo mongod --auth

MongoDb will now start up, run the scripts that create our users and then restart in authentication mode.

Now we can authenticate to our database using our new appuser like this (using MongoDB.Driver for C#):

var mongoSettings = MongoClientSettings.FromConnectionString(config.ConnectionString);
mongoSettings.Credential = MongoCredential.CreateCredential("admin", config.Username, config.Password);
var client = new MongoClient(mongoSettings);