Docker for Developers - Setting up MongoDB

Moving forward in the series... this article will teach how you can save plenty of time using Docker compose and Dockerfile. I will be building the files incrementally, so you can learn the nuances along the way. You can follow along if you like, but it is not necessary, since I will be documenting everything here. This article assumes that you already know about the MEAN stack, Git and have been following the Docker series.

Series

Part 1: Docker for Developers - Setting up your developer machine
Part 2: You are HERE
Part 3: Docker for Developers - Setting up Node.js
Part 4: Docker for Developers - Load Balance using Nginx

In this article you will learn about setting up MongoDB and some nuances about persisting data using volumes.

Let's dive into the Docker goodness

Step 1: Download the seed project

Open a terminal and type git clone https://github.com/attosol/nginx-and-nodejs-on-docker.git.

Step 2: Change your directory and checkout the first commit

$ cd nginx-and-nodejs-on-docker
$ git checkout a9caad2cc

Review the docker-compose.yml file. It will look as follows:

version: '2'

services:  
  database:
    image: ${DATABASE_VERSION}
    networks:
      - backend
    container_name: ${DATABASE_CONTAINER_NAME}
    volumes:
      - mongo-data:/data/db
      - ./docker/scripts:/scripts
      - ./docker/data:/data

networks:  
  backend:
    driver: bridge

volumes:  
  mongo-data:

Step 3: Docker magic in action

Run docker-compose up -d

Creating network "nodenginxseed_backend" with driver "bridge"  
Creating volume "nodenginxseed_mongo-data" with default driver  
Creating mongodb ...  
Creating mongodb ... done  

That one little command did a bunch of things for you! To use MongoDB now run the following:

$ docker exec -it mongodb bash
root@568df5929409:/# 

# There is a file called "/data/sample.json", that you can use to seed your database with data. 
# There is a script too! Let's allow execution of script and execute it.
root@568df5929409:/# chmod 755 ./scripts/mongoseed.sh  
root@568df5929409:/# ./scripts/mongoseed.sh 

REMOVING Sample Database  
==========================
MongoDB shell version v3.4.8  
connecting to: mongodb://127.0.0.1:27017/sample  
MongoDB server version: 3.4.8  
{ "ok" : 1 }

Importing Documents in a new Database called Sample  
===================================================
2017-09-08T09:42:50.910+0000    connected to: localhost  
2017-09-08T09:42:50.931+0000    imported 100 documents

DONE!

# Fetch data if you like :)
root@568df5929409:/# mongo sample  
> db.users.find({"name":"Mitchell Herrera"}).pretty()

You can see, how easy it was to install MongoDB and initialise it with data, that too WITHOUT installing anything on your OS (except Docker)? Now, let's see what's going on in a little more detail.

Explanation of the Docker goodness

.env file

The .env file that you see at the root of the project, contains all the variables that you reference to in the docker-compose.yml.

# Project Information
COMPOSE_PROJECT_NAME=node-nginx-seed  
TAG=1.0

# Database Information
DATABASE_VERSION=mongo:3.4.8  
DATABASE_CONTAINER_NAME=mongodb  

docker-compose.yml file

The docker-compose.yml file is also created at the root of the project where you will be running docker-compose commands from. It contains instructions about building your environment. Consider this an effort in the right direction since it will help you save plenty of time during development.

It is a YML (rhymes with camel) file, and starts with version attribute (set to 2 or higher). The service attribute lets you tell Docker about the containers you would like to spin and has a 1:1 relationship with the containers. Thus, every service will spin up a unique container. If you have a docker-compose.yml file like the following, you will be able to create a network and spin a database container by executing an extremely simple docker-compose up command:

version: '2'

services:  
  database:
    image: ${DATABASE_VERSION}
    networks:
      - backend
    container_name: ${DATABASE_CONTAINER_NAME}
    volumes:
      - mongo-data:/data/db
      - ./docker/scripts:/scripts
      - ./docker/data:/data

networks:  
  backend:
    driver: bridge

volumes:  
  mongo-data:
  • database - One of the service that implies role of the container.
  • image - Tells Docker which image to pull from dockerhub. DATABASE_VERSION is a variable declared in the .env file as you have seen above.
  • networks - Uses a defined bridge network called backend.
  • container_name - This is a friendly container name. In this example it is mongodb
  • volumes - This is the secret sauce due to which the data is persisted. Notice that there are three mappings:
    • mongo-data which is mapped to /data/db. This is the place where mongo creates its database by default.
    • ./docker/scripts is mapped to /scripts. Basically, it is telling Docker that, "hey... when I say /scripts, I mean... ./docker/scripts on my local box".
    • In a similar way, /data is mounted as ./docker/data inside of the container.

/scripts/mongoseed.sh file

This is a regular shell script that is currently available in the /scripts folder. To execute this script, you have to get inside of the container as you have already seen in the section above: Docker magic in action. Basically, you run docker in interactive mode and supply the friendly name like:

$ docker exec -it mongodb bash

Once you are in, you can run any command as you would. The mongoseed.sh file looks as follows:

#!/bin/bash

if [ -e /scripts/.seeddata ]  
then  
  printf "\nWARNING"
  printf "\n==========\n"
  printf "Data already seeded!\n"
  printf "If you want to remove and reseed, run 'rm /scripts/.seeddata'\n\n"
else  
    printf "\nREMOVING Sample Database\n==========================\n"
    mongo sample --eval "db.dropDatabase()"
    printf "\nImporting Documents in a new Database called Sample\n"
    printf "===================================================\n"
    mongoimport --db sample --collection users --file /data/sample.json --jsonArray
  touch /scripts/.seeddata
  printf "\nDONE!\n"
fi  

Type exit to get out of the container.

NOTE: The sample.json file is created using this fabulous tool http://www.json-generator.com/.

You can now run the following to discard all your changes and switch back to master branch.

$ git clean -f
$ git checkout master

What next?

Well, stay tuned for upcoming articles! Say hi, share this article, leave a comment or subscribe now to stay updated through our monthly newsletter. Also, check out our services or contact us at contact@attosol.com for your software and consultancy requirements.

Happy Docking!

Ads:

Rahul Soni

⌘⌘ Entrepreneur. Author. Geek. ⌘⌘

Kolkata, India

Subscribe to Attosol Technologies

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!