4 minute read

There are instances when you want to create MongoDB instance in Docker to use in production or in local/internal. We came across this requirement where we were using MongoDB Atlas for production but wanted to use MongoDB docker in our local/internal/dev environment. Mongo Atlas uses SSL connection so we want to keep our local consistent with production environment. In this post, I am going to explain the process of creating Mongo Docker instance with valid SSL certificate and replicating same behavior of MongoDB Atlas.

Note: You can use same process for your production MongoDB instance as well, if you are not using any cloud solution for MongoDB

All the code related to this post (except certificates) is available in GitHub Repo for your reference.

Prerequisites

Step 1. SSL Certificates

If you don’t have valid SSL certificate (not self-signed) issued by Certificate Authority please read and follow Getting Valid SSL Certificate from Let’s Encrypt for LocalHost else skip this step.

Step 2. Docker

Creating Required Files

Step 1. Create a project folder and inside that project folder create scripts and ssl folder. scripts folder will contain script to create user in MongoDB and start it. ssl will contain SSL certificate e.g. CA Root and certificate for MongoDB.

Step 2. Copy CA Root certificate and MongoDB certificate in ssl folder.

$ ls
ca.pem      mongodb.pem

Step 3. Create a Dockerfile as following in your project root folder. We are going to use official MongoDB docker container from docker hub.

FROM mongo:3.6.2-jessie

COPY scripts /home/mongodb/scripts

COPY ssl /home/mongodb/ssl

COPY mongod.conf /home/mongodb

WORKDIR /home/mongodb

RUN ["chmod", "+x", "/home/mongodb/scripts/"]

CMD ["/home/mongodb/scripts/run.sh"]

Note: In mongo:3.6.2-jessie, 3.6.2-jessie is tag which I am using. If you want to use latest Mongo container than remove :3.6.2-jessie

Step 4. Create mongod.conf file in the same root folder.

net:
  bindIp: 0.0.0.0
  port: 27017
  ssl:
    CAFile: /home/mongodb/ssl/ca.pem
    PEMKeyFile: /home/mongodb/ssl/mongodb.pem
    mode: requireSSL
    disabledProtocols: "TLS1_0,TLS1_1"
    allowConnectionsWithoutCertificates: true
storage:
  journal:
    enabled: true

Step 5. Now, Go to scripts folder and create run.sh and setup_user.sh files

Content of run.sh:

#!/bin/bash

sleep 5

chown -R mongodb:mongodb /home/mongodb

nohup gosu mongodb mongod --dbpath=/data/db &

nohup gosu mongodb mongo admin --eval "help" > /dev/null 2>&1
RET=$?

while [[ "$RET" -ne 0 ]]; do
  echo "Waiting for MongoDB to start..."
  mongo admin --eval "help" > /dev/null 2>&1
  RET=$?
  sleep 2
done

bash /home/mongodb/scripts/setup_user.sh

gosu mongodb mongod --dbpath=/data/db --config mongod.conf --bind_ip_all --auth

Content of setup_user.sh:

#!/bin/bash

echo "************************************************************"
echo "Setting up users..."
echo "************************************************************"

# create root user
nohup gosu mongodb mongo DBNAME --eval "db.createUser({user: 'admin', pwd: 'YOUR_PASSWORD', roles:[{ role: 'root', db: 'DBNAME' }, { role: 'read', db: 'local' }]});"

# create app user/database
nohup gosu mongodb mongo DBNAME --eval "db.createUser({ user: 'myuser', pwd: 'YOUR_PASSWORD', roles: [{ role: 'readWrite', db: 'DBNAME' }, { role: 'read', db: 'local' }]});"

echo "************************************************************"
echo "Shutting down"
echo "************************************************************"
nohup gosu mongodb mongo admin --eval "db.shutdownServer();"

Pro Tip: You can create variables for commonly used commands in the file.

Creating Docker Instance

Step 1. Go to project root folder which contains Dockerfile and run it to create docker image

$ docker build -t mongo .

Sending build context to Docker daemon  24.58kB
Step 1/7 : FROM mongo:3.6.2-jessie
 ---> 0f57644645eb
Step 2/7 : COPY scripts /home/mongodb/scripts
 ---> 8041e28c2137
Step 3/7 : COPY ssl /home/mongodb/ssl
 ---> ac293a519709
Step 4/7 : COPY mongod.conf /home/mongodb
 ---> ec399118fc0e
Step 5/7 : WORKDIR /home/mongodb
Removing intermediate container 6749cb04ff21
 ---> 0a5a5e3d4911
Step 6/7 : RUN ["chmod", "+x", "/home/mongodb/scripts/"]
 ---> Running in 64e50080f584
Removing intermediate container 64e50080f584
 ---> ce679220fcea
Step 7/7 : CMD ["/home/mongodb/scripts/run.sh"]
 ---> Running in 5044246929c9
Removing intermediate container 5044246929c9
 ---> dee2ad41b921
Successfully built dee2ad41b921
Successfully tagged mongo:latest
  • mongo:latest is the tag name which we are going to use in next step.

Step 2. Now, run Docker image to create a container.

$ docker run -d -p 27017:27017 --mount source=mongodb,target=/data/db --mount source=configdb,target=/data/configdb --name mymongo mongo:latest
937a234022eb718edfbffec1d4dd35e31b5eb23e78f08776312f81b63535f848
  • 937a234022eb718edfbffec1d4dd35e31.... is container ID created by command.
  • mongodb and configdb are volumes to keep data on your local so that when you destroy your container you will still have your data. If you don’t want to keep data of previous container, remove --mount option and it’s arguments.
  • mymongo is name of your container which you can use to run any command in that container.

Step 3. You can check logs of the container by docker logs -f <CONTAINER ID OR NAME>

docker logs -f mymongo

Step 4. Create an entry in your /etc/hosts file for the domain name which you have used to obtain your certificate. see this

127.0.0.1           localhost ry-dev.herokuapp.com
  • ry-dev.herokuapp.com is the domain name I used to get my SSL certificate.

Step 5. Now, you can try connecting to your MongoDB instance in docker

mongo --ssl --host ry-dev.herokuapp.com --port 27017 --username <USERNAME> --password <PASSWORD> --authenticationDatabase <DBNAME>
  • Replace value of <USERNAME>, <PASSWORD> and <DBNAME> with the values which you have used in setup_user.sh file.
  • You should not see any error related to certificate validation and should be connected to MongoDB successfully.
  • You should not need to use command --sslAllowInvalidCertificates option from command line to connect to your MongoDB. If you do get error, please check you have correct CA Root certificate and application certificate.

Useful Docker Commands

  • Check status of your container by docker ps -a
  • Check logs of the container by docker logs -f <CONTAINER ID OR NAME>
  • Remove any container docker rm <CONTAINER ID OR NAME>
  • Get shell in container docker exec -it <CONTAINER ID OR NAME> bash

Leave a Comment