How to setup user authentication in MongoDB 3.0
MongoDB Authentication example
Docker now supports adding host mappings
A sample Docker workflow with Nginx, Node.js and Redis
Setting up a Replicated MongoDB using Authentication in Docker on DigitalOcean
$ docker run --name mongo -v "$PWD"/mongo/data:/data/db -p 27017:27017 -d mongo
- First we need to connect to the database from another mongo container
$ docker run -it --link mongo:mongo --rm mongo sh -c 'exec mongo "mongo:27017/test"'
- Adding users When you're connected to the MongoDB you're going to want to switch to the Admin database, using,
$ use admin
Now we can add users. Create a new site admin user called siteUserAdmin,
$ db.createUser ({
user: "siteUserAdmin",
pwd: "siteUserAdmin",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
});
and a Root User called siteRootAdmin,
$ db.createUser ({
user: "siteRootAdmin",
pwd: "siteRootAdmin",
roles: [ { role: "root", db: "admin" } ]
});
Now exit the mongo-container with the apply named command exit
- Stop the mongo again, and remove it
$ docker stop mongo
$ docker rm -f mongo
To start database again and enable authentication let add --auth
flag in command,
$ docker run --name mongo -v "$PWD"/mongo/data:/data/db -p 27017:27017 -d mongo --auth
We need connect again to mongo database with command in previous section and connect to hitdb
,
$ use hitdb
Let's create user for hitdb
,
$ db.createUser ({
user: "hitdbadmin",
pwd: "hitdbadmin",
roles: [ { role: "root", db: "admin" } ]
});
Now, the hitdb
is already to using for node.js application.
We will create an simple application with only one feature which there are request (GET method) from client, application will count up one and save result into hitdb
(this database is created in previous section).
Let start by installing Express.js,
$ npm install express
and Mongodb driver,
$ npm isntall mongodb
Let's create file src/app.js
and input code such as,
'use strict';
const app = require ('express') ();
module.exports = function createApp (db) {
app.get ('/hit', (req, res) => {
let collection = db.collection ('hitcollection');
collection.findOne ({name:'hit'})
.then ((doc) => {
if (doc) {
collection.updateOne ({name:'hit'},{$set: {count: doc.count + 1}})
.then ((docUpdate) => {
res.status (200).send (`Hit ${doc.count+1}`);
})
.catch ((error) => {
res.status (500).send ('Server error');
});
} else {
collection.insertOne ({name:'hit', count: 1})
.then ((docCreated) => {
res.status (201).send ('Hit 1');
})
.catch ((error) => {
res.status (500).send ('Server error');
});
}
})
.catch ((error) => {
res.status (500).send ('Server error');
});
});
return app;
}
This code is simple creating an Express.js app with parameter is mongodb (db
). You can understand code will do,
- Try to finding in database document with name
hit
in collection with namehitcollection
- If
hit
document is exist, let update count up to one and save again to database. - If
hit
document is not exist, let create new one and save to database with count is1
.
Next, we create src/index.js
to connecting to hitdb
database and start express application, let's input code such as,
'use strict';
const app = require ('./app');
const mongodb = require ('mongodb');
let MongoClient = mongodb.MongoClient;
const mongoUrl = 'mongodb://hitdbadmin:hitdbadmin@mongo:27017/hitdb';
const port = process.env.PORT | 3000;
MongoClient.connect (mongoUrl, (error, db) => {
if (error) return console.error ('Cannot connect to MongoDB. Error', error);
console.log ('Connect to MongoDB successful!');
app(db).listen (port, () => console.log ('Application listen at ' + port));
});
This code start connection to mongodb with Mongodb driver and Url mongodb://hitdbadmin:hitdbadmin@mongo:27017/hitdb
with,
hitdbadmin:hitdbadmin
is user and password ofhitdb
mongo:27017
is address of mongo in docker
Note: If mongo is installed same machine or test with current mongo in docker, you can use
localhost:27017
or127.0.0.1:27017
Now, start the nodejs application you will see,
$ node src/index.js
Connect to MongoDB successful!
Application listen at 3000
Let's count up hit with curl
in terminal
$ curl localhost:3000/hit
Hit 1% $ curl localhost:3000/hit
Hit 2%
Yeah, nodejs application is done. Let's dockerize application with Dockerfile such as,
# Start with base image from official
FROM node:6.9.2-alpine
MAINTAINER duytran
# Change workdir
WORKDIR /app
# Add current src and install file
ADD src src
ADD package.json package.json
# Run update and install package for application
RUN npm update
# Start application
CMD node src/index.js
And build it with command,
$ docker build -t node-hit .
Start nodejs application docker,
$ docker run -d --name node-app --link mongo:mongo -p 3000:3000 node-hit
To make sure, node application start successful, type command,
$ docker logs node-app
Connect to MongoDB successful!
Application listen at 3000
Ok, Everything done. Let's move to next secion.
We need pull Nginx image from DockerHub. Execute the following bash command to do just that:
$ docker pull nginx:latest
We'll be using a custom nginx/nginx.conf
file that will be mapped to the containers /etc/nginx
directory. Here is the server portion whichs defines the proxy to the node.js server
...
server {
listen 80;
index index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/public;
location ~* /hit {
proxy_pass http://node-app:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
The configuration will proxy requests to the url /hit
to the Node.js Docker container! Note the proxy_pass entry, uses the name of the Node.js Docker container, node-app
, that was created.
To create the Nginx container execute the following bash command from the project root directory:
$ docker run -d --name web -p 8080:80 -v $(pwd)/web/src:/var/www -v $(pwd)/nginx/nginx.conf:/etc/nginx/nginx.conf --link node-app:node-app nginx
Confirm the Nginx Docker container is running by executing the following bash command:
$ docker ps
You should see a running container with the name web.
Point your browser to http://localhost:8080
. CLick on the link labled HIT and that will take you to the nodejs server! Notice the link does not contain the port 3000. This is because Nginx is configured to use the /hit url as a proxy to the nodejs server.
Full source code for this example docker-node-mongo-nginx