Welcome to weblogs.com.pk Sign in | Join | Help

Dockerizing Mongo and Express

Dockerizing Node

Now that we are familiar with the Docker and how it helps us in high isolation and compartmentalization; lets expand and try out deploying some real world application. I will be using the application that we built for MongoDB and Mongoose; its an Express JS / MongoDB application and we will try deploying it across two Docker containers; one for MongoDB and the other for Express in spirit of Microservice Architecture. As per wikipedia; Microservices are a more concrete and modern interpretation of service-oriented architectures (SOA) used to build distributed software systems. Like in SOA, services in a microservice architecture are processes that communicate with each other over the network in order to fulfill a goal. Also, like in SOA, these services use technology agnostic protocols. Using separate Container for each microservice; we get fine control and can monitor and distribute components of our application at each microservice level.

For MongoDB; lets start an Ubuntu instance; install Mongo and try to run it; we will learn that it needs /data/db directory

image

We can create that in the container but as we know that when container is stopped it loses the data. Its recommended to use Data Volume for such requirement and we will mount one as /data/db. Lets create a Dockerfile for our MongoDB container

FROM ubuntu
MAINTAINER Khurram <khuziz@hotmail.com>

RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
RUN echo "deb
http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.2.list
RUN apt-get update && apt-get install -y mongodb-org

EXPOSE 27017

ENTRYPOINT ["/usr/bin/mongod"]

Lets create a Dockerfile for the Node JS as well; we will not be including the application code in the Node JS container instead we will use Data Volume for the application files. Note that Node is not being run as ENTRYPOINT or CMD; we will be starting it as a parameter to the container in docker run command and pass the start up JS file as the parameter; this way we can reuse our Node JS container image for different applications; scenarios like running web service in its own container and front end application in separate container

FROM ubuntu
MAINTAINER Khurram <khuziz@hotmail.com>

RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y nodejs
RUN apt-get install -y build-essential
RUN apt-get install -y npm

To build the container images; give commands

docker build -t khurram/node -f Dockerfile.node .
docker build -t khurram/mongo -f Dockerfile.mongodb .

  • I have kept different name for the Dockerfile for our containers; as these names are not standard I am passing the file name using –f argument; its done so that I can have both files in one directory
  • Its better to make a BAT / SH script for above commands

Before running the two docker containers; we need two data volumes, one for Mongo and the other for Node application. For the Node application we will use host directory; in our case the directory in Boot2Docker VM; we will use cifs-utils to mount the folder from Windows HyperV Host sharing it on network as discussed in Docker on Windows- Customized Boot2Docker ISO with CIFS; from there on it can act as a host directory in Docker VM and we can use it for data volume. Unfortunately we cant use this arrangement for Mongo as it expects certain features from the file system (for its data locking etc) and mounted directory using cifs-utils doesnt have these features, therefore we will create a volume using docker and use it instead

docker volume create --name mongo-data
mongo-data

docker volume inspect mongo-data
[
    {
        "Name": "mongo-data",
        "Driver": "local",
        "Mountpoint": "/mnt/sda1/var/lib/docker/volumes/mongo-data/_data",
        "Labels": {}
    }
]

To start the Mongo container issue this command

docker run -d -p 27017:27017 -v mongo-data:/data/db --name mongodb khurram/mongo

  • The above created mongo-data volume is passed using –v argument
  • Its mounted as /data/db in the container as required by the Mongo we learned by installing it in a test container
  • The Mongo port is exposed; we can test by connecting to Docker VM from the development machine!

Docker has a Linking feature; using which we can link one or more containers to particular container while starting it; doing so it adds /etc/hosts entry as well as set Environment Variables. Its important that the linking container is given proper name; you will see that /etc/hosts entry and environment variables all depends on it. Lets start the khurram/node instance linking mongodb container that we already have started!

docker run -it -v /mnt/srcshare/HelloExpress:/app --link mongodb:mongodb --name helloexpress khurram/node
root@7be354a7e084:/# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      mongodb 75e912d09a6c
172.17.0.3      7be354a7e084
root@7be354a7e084:/# set
BASH=/bin/bash
….
MONGODB_NAME=/helloexpress/mongodb
MONGODB_PORT=tcp://172.17.0.2:27017
MONGODB_PORT_27017_TCP=tcp://172.17.0.2:27017
MONGODB_PORT_27017_TCP_ADDR=172.17.0.2
MONGODB_PORT_27017_TCP_PORT=27017
MONGODB_PORT_27017_TCP_PROTO=tcp

UID=0
_=/etc/hosts
root@7be354a7e084:/# cd /app/
root@7be354a7e084:/app# ls
DockerBuild.bat  DockerRun.bat       Dockerfile.node       HelloExpress.sln  bin     node_modules  package.json  routes
Dockerfile.mongodb  HelloExpress.njsproj  app.js            models  obj           public        views

  • Given it has added /etc/hosts entry; we can simply access the mongodb server with the name in connection string for mongoose.connect() call
  • Note that the information about the mongodb’s exposed port is also available in the environment variables
  • Note that the cifs mounted “local” directory is mounted as volume in the container and we can access its content accordingly

Once the data volumes are in place; and container linking is understood and app.js is updated accordingly for mongoose.connect(); lets clean up and start the fresh instances of our containers

docker stop mongodb
docker stop helloexpress

docker rm mongodb
docker rm helloexpress

docker run -d -v mongo-data:/data/db --name mongodb khurram/mongo
docker run -d -p 3000:3000 -v /mnt/srcshare/HelloExpress:/app --link mongodb:mongodb --name helloexpress khurram/node nodejs /app/bin/www

  • Its better to make a BAT / SH script for the above commands

Code @ https://github.com/khurram-aziz/HelloExpress is updated accordingly having the DockerBuild.bat, DockerRun.bat and Dockerfiles for Mongo and Node

Resources

Published Monday, July 04, 2016 1:08 PM by khurram

Comments

No Comments

New Comments to this post are disabled