Deploying node clusters using docker

Posted by venky_lb on Tue, 14 Dec 2021 04:54:43 +0100

This article will demonstrate how to deploy node clusters through docker through three simple demos.

If you want to learn docker, Official documents It's a good introduction guide, or you can see this gitbook.

1, Deploy node container

First, prepare a node service demo. The code is as follows:

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
    ctx.body = 'Hello World';
});

app.listen(8080);

Deploy node services

The simplest way to create your own node service image is to add your own content based on the existing node image. You can describe your own node image through Dockerfile. The content is as follows:

FROM node:8.9.1

# Copy the current code to the specified directory
ADD . /home/app
WORKDIR /home/app
RUN npm install

EXPOSE 8080
CMD ["npm", "run", "dev"]

After you have the image file, you can build the image through docker build:

docker build -t node-demo .  
# -t means to define the image name

To view the currently built image:

docker images

Run container through mirror:

docker run -d -p 8080:8080 node-demo 
# -d indicates background operation

To view running container information:

docker ps

To view the container run log:

docker logs xxx
# xxx is the container id

Pause container:

docker container stop xxx

Because the underlying image is a linux image, you can connect to the container bash:

docker exec -i -t xxx bash

2, Deploy node and redis services

Based on the code in the first step, we use node to connect a redis to simulate the function of counting visitors. The modified node code is as follows:

const Koa = require('koa');
const bluebird = require("bluebird");
const redis = require("redis");
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
const app = new Koa();

// Note that the host here is specified as redis, which is a function provided by docker compose
let host = 'redis';
let port = '6379';

let client = redis.createClient({
    host,
    port
});

app.use(async ctx => {
    if (ctx.path == '/incr') {
        let num = await client.getAsync('num');
        num++;
        client.set('num', num, redis.print);
        return ctx.body = `num is ${num}`;
    }
    ctx.body = 'Hello World';
});

app.listen(8080);

The node service needs to be connected to the redis service. Docker provides a compose tool to simplify the communication between containers. To use the compose function, you need to define the description file docker compose yml:

version: '3'
services:
  web:
    build: .
    ports:
     - "8080:8080"
  redis:
    image: "redis:alpine"

Two containers, web and redis, are described here, corresponding to node and redis respectively.

Then start the container through docker compose. By default, if no image is built, the image will be built or pull ed first:

docket-compose up -d

To view container operation:

docker-compose ps

Pause container:

docker-compose stop

3, Deploy node cluster

The final example is to start multiple node containers to form a cluster, and then access the same redis:

It is actually easy to use the instance extension provided by docker, as long as you modify docker compose YML as follows:

version: '3'
services:
  web:
    image: node-demo
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
    ports:
     - "8080:8080"
  redis:
    image: "redis:alpine"

The only difference is that the deploy declaration is added to specify the number of node instances and resources.

For real cluster deployment, docker provides swarm function, which is very powerful and can manage cross machine deployment. Here, only the simplest instance extension is used.

First create a cluster:

docker swarm init

Then deploy the cluster

docker stack deploy -c docker-compose.yml node-swarm

View cluster operation

docker service ls

Then check the operation of the container

docker container ls

You can see that there are currently six containers running, one redis container and five node containers.