Setup docker swarm

Microservice architecture is a style of componentizing monolith applications using service orientation. These services may use various technologies, programming  languages, and data-storage technologies. Some of these technologies may have conflicts with each other on resources such as memory, port, CPU, IO, name spaces or environmental variables. For instance one piece of our application may use java 6 and the other piece may use java 8. This made deployment to production a difficult phenomena for dev ops.

Virtualization is a way of avoiding this problem by sharing resources among isolated environment. This virtualization may happen for hardware layer in which 2 layers of OS appear and come with the waste of lots of disk and resources or may happen on sharing a same OS among different containers which is pretty much a light weight isolation level. Docker is the most popular way of containerization, even though, it needs some other tools for managing these containers. This post helps you understand more how docker virtualizes OS for an application.

In this post I am going to show how to set up a docker swarm and how to containerize your node.js/java app and run that image in your docker swarm.

docker-swarm

Prerequisite:

First we are going to setup a swarm environment with one managers and 3 worker node. You may need 3 VMs with either ubuntu, Redhat, centos, etc to host your manager and worker nodes. The manager can be hosted on the same node as your worker nodes. You can also have high availability for your manager which means you can have a manager installed on a same machine that your have your worker node. Manager is a part of docker daemon which is installed with your docker machine.

The first step is to install docker machine on all of your hosts. you can do so by the following command:

1- Update your yum package:

$ sudo yum update

2- Run installation script:

$ curl -sSL https://get.docker.com/ | sh

3- Configure and start Engine so it listens for Swarm nodes on port 2375

$ sudo docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

4- Verify that Docker Engine is installed correctly:

$ sudo docker run hello-world

5- Initialize you swarm cluster on the current machine and make this machine a manager:

docker swarm init --advertise-addr <IP-address-of-manager>

6- Now do steps 1-4 on the other 3 VMs and join them to the swarm by the following commands: Please note that the initialize command gives you different tokens for joining as manager or worker node.

To add a worker to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-343oklx5y9zqwc129p4ttvgxeeexh49vpgslavcnqzipjmp2n4-0375hm0z4nto02l8jbt08ga1n \
    <IP-address-of-manager>:2377

To add a manager to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-343oklx5y9zqwc129p4ttvgxeeexh49vpgslavcnqzipjmp2n4-bnfuijeolp487mllvj7l9sjil \
    <IP-address-of-manager>:2377

7- create an overlay network by:

docker network create -d overlay mynet

Congratulations, you have configured your swarm cluster.

Create an image from you node.js app:

The first steps are related to creating a node.js app by creating the following files

1- Create package.json:

{
  "name": "docker_web_app",
  "version": "1.0.0",
  "description": "Node.js on Docker",
  "author": "First Last <first.last@example.com>",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.13.3"
  }
}

2- create server.js which uses express.js framework:

'use strict';

const express = require('express');

// Constants
const PORT = 8080;

// App
const app = express();
app.get('/', function (req, res) {
  res.send('Hello world\n');
});

app.listen(PORT);
console.log('Running on http://localhost:' + PORT);

The above app is runnable if you run “npm i” and run "node ."

Now lets create a docker file:

3- Create the Dockerfile with these contents:

FROM node:argon

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install

# Bundle app source
COPY . /usr/src/app

EXPOSE 8080
CMD [ "npm", "start" ]

The first line tells to use node:argon image which already has node.js installed in that image as a prototype image. In the next lines we are installing our application that created in steps 1-2 and installing dependencies for that application. finally we are exposing the port that app is supposed to run and we start the app.

4- Build docker image by:

$ docker build -t <your username>/node-web-app .

Now $ docker images shows this image added to the list of images in your machine:

$ docker images

# Example
REPOSITORY                      TAG        ID              CREATED
node                            argon      539c0211cd76    3 weeks ago
<your username>/node-web-app    latest     d64d3505b0d2    1 minute ago

You can now run your image manually as a container with the following command

$ docker run -p 49160:8080 -d <your username>/node-web-app

or use docker swarm to create a service from your app and run it in your swarm cluster with 4 instances of you app running in the cluster:

docker service create --name node-app-v1 --replicas=4 --network mynet -p8080:8080 bhajian/node-web-app

Now if you hit your manager IP with the port 8080 you should get Hello world! message.

$ curl http://<manager-ip>:8080
Hello world!