Blake Mitchell
Jul 27, 2016 · 11 min read
Image for post
Image for post

Updated for release v1.12.3: minor command changes once again, labels now applied at the node level, and no more need for custom mongo image.

Running a MongoDB Replica Set on Docker 1.12 Swarm Mode: Step by Step

With swarm mode, Docker 1.12 introduces some exciting new features for orchestrating a highly available cluster of services. This video from DockerCon 2016 gives a great overview, and there are many other excellent sessions online as well.

Docker swarm mode services are a collection of tasks (containers for now) dynamically allocated across the cluster. This is good for many reasons, but it means your application’s containers may move from one box to another, leaving their data volumes behind. For a database, that could be a sub-optimal situation. Fortunately many database systems already have high-availability baked in. All we have to do is keep the containers in one place, and the DBMS will take care of the rest.

Strategy

The basic plan is to define each member of the replica set as a separate service, and use constraints to prevent swarm orchestration moving them away from their data volumes. This preserves all the operational benefits that Docker provides, while nullifying the redundant (and in this case harmful) fault recovery features.

A brief note on conventions used in this post. I will bold everything that I typed into the terminal. I apologize for the verbosity and line wrapping of the output, but I think it is important to show everything that is happening. Also, don’t attempt to copy/paste any commands from the non-fixed-width paragraphs; Medium insists on “fixing” text, borking hyphens, quotes, spacing, and other important punctuation.

Inspect the Environment

For this example I will go from scratch with a Docker Toolbox 1.12.3 installation and set up a highly available Node.js app with a MongoDB 3.2 replica set as the data store. I will be doing this on my Windows 7 laptop, but the commands should be identical on other platforms. First thing to do is open the Docker Quickstart Terminal and get the lay of the land.

Provision Docker Machines

I don’t need the default machine, so I’m going to get rid of it, and create three new ones for the cluster. As this is a development environment, I will only have one cluster manager node, and two worker nodes. In production multiple managers should be used for fault tolerance.

PuTTY Interlude

Now that the VMs are running, I’m going to switch over from the Docker Quickstart Terminal to PuTTY. I find the interface much more user friendly. This is optional and doesn’t affect operation of the swarm cluster. I used PuTTYGen to convert each of the private keys to a format PuTTY understands. Then I connected to each VM via SSH with the username “docker” and the private key for authentication. Here are all the relevant keys, after I did the conversion.

Create the Swarm

Next I’ll initialize the swarm on the manager, and join both of the workers. Most of this comes directly from the Getting started with swarm mode tutorial. It is important to specify the “ — listen-addr” parameter when using docker-machine and VirtualBox, as the VMs are assigned multiple network interfaces.

You can see from the “docker info” output, I now have a three node swarm with one manager.

Preparing for MongoDB

It order to keep the mongo services pinned to the same nodes as their data volumes, I am setting a label “mongo.replica” on each of the nodes. I will use these labels in constraints when creating the services later.

The replica set will need an overlay network to allow the replicas to communicate, and accept connections from the application. Each replica also needs a volume for data and configuration. I will give each of the volumes a numerical suffix that matches the “mongo.replica” label for the underlying node. This is not required, but helps me keep track of them.

Create the MongoDB Services

Now it’s time to create the MongoDB services that will comprise the replica set. I will use the official mongo image from DockerHub.

The command to create each service is long, let me break the first one down a little: we’re asking docker to create a new service, with a single instance, on the “mongo” network, mounting the “mongodata1” and “mongoconfig1” volumes, running on the node where the label “mongo.replica” has value “1” with service name “mongo1”, using the image “mongo:3.2” and run the command “mongod -replSet example”.

It will take some time to pull the images the first time, use the “REPLICAS” column from “docker service ls” to see when all the service tasks are running. (Docker service replicas and MongoDB replicas are not the same thing, the former are redundant tasks (containers) in a service managed by the swarm, where as the latter are MongoDB instances participating in a replica set.)

Initiate the Replica Set

Next I’ll set up the MongoDB replica set. I am following the Deploy a Replica Set instructions from the documentation. First I will initiate the replica set with a single member configuration, then add the other two members. Because the services are on a private network, I will exec the mongo client already present in the running container to issue commands. This also demonstrates how to use one of the swarm assigned labels to identify containers.

There it is, a healthy replica set!

Put an App on it

Now that I have a functioning replica set, I’m going to put a Node.js app in front of it to demonstrate the capabilities. I’m going to use the post-it board Koalab, because it gives a nice visual and everything is stored in MongoDB. The publisher of Koalab does not push it to Docker Hub, so I have taken care of that.

As you can see, my MONGO_URL addresses the entire replica set, and I attached this service to the “mongo” network. Now I can hit port 8080 on any of my swarm hosts and create a new post-it board. Even though there are only two copies of kalahari/koalab running, the magic of swarm networking makes the service available everywhere.

Thanks for taking the time to read, I hope it was informative, and allows you to benefit from my trial and error. If you have any questions, feel free to ask below, or ping me on twitter.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store