Deploying simple services through Docker Swarm

This tutorial will introduce how to use docker swarm to arrange and distribute friendly hello: v4. This service can be accessed by browser to get the Hostname of the current node. The final effect is as follows:

STEP 1: Creating Virtual Machines

In order to simulate the cluster environment, we create three virtual machines, one as manager node and the other two as worker node. My own mac is 8g memory. Although it's a bit urgent, the three VMS are still able to support:

$ docker-machine create manager
$ docker-machine create worker-1
$ docker-machine create worker-2

Then enter the three virtual machines separately (open three terminal s to operate):

$ docker-machine ssh manager
$ docker-machine ssh worker-1
$ docker-machine ssh worker-2

STEP 2: Initialize Cluster

First, confirm the IP of each vm:

$ ifconfig

For example, the three IPS I have now are:

  • manager: 192.168.99.112
  • worker-1: 192.168.99.113
  • worker-2: 192.168.99.114

Then in manager, execute:

$ docker swarm init --addvertise-addr <Your manager Nodal ip>

# My own orders:
$ docker swarm init --addvertise-addr 192.168.99.112

After completion, the command of replicating the output to join the swarm cluster is executed in two worker s separately. The final effect is as follows:

STEP 3: Create friendly hello: V4 service

We first create two files directly in the current directory, app.py Docker file, and add the following code:

  • app.py

    from flask import Flask
    from redis import Redis, RedisError
    import os
    import socket
    
    # Connect to Redis
    redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
    
    app = Flask(__name__)
    
    @app.route("/")
    def hello():
        try:
            visits = redis.incr("counter")
        except RedisError:
            visits = "<i>cannot connect to Redis, counter disabled</i>"
    
        html = "<b>HostName:</b> {host_name}<br/>" \
               "<b>Hostname:</b> {hostname}<br/>" \
               "<b>Visits:</b> {visits}"
        return html.format(host_name=os.getenv("HOSTNAME", "UNKNOWN"),
                           hostname=socket.gethostname(), visits=visits)
    
    if __name__ == "__main__":
        app.run(host='0.0.0.0', port=5000)
  • Dockerfile

    FROM python:3.7-slim
    
    WORKDIR /app
    
    COPY . /app
    
    RUN pip install flask redis -i https://mirrors.aliyun.com/pypi/simple  --trusted-host mirrors.aliyun.com 
    EXPOSE 5000
    
    CMD ["python", "app.py"]

Then build the image:

$ docker build -t friendlyhello:v4 .

Then the service is created by docker service creation, and the -- replicas 3 parameter means creating three copies:

$ docker service create --replicas 3 -p 5000:5000 --name friendly friendlyhello:v4

After success, we can see the task s of this service:

$ docker service ps friendly

However, we found that only the task of the manager node started, and both worker nodes indicated that there was no mirror, so we need to do distribution next.

STEP 4: Quickly distribute mirrors to all nodes

Let's shrink down first.

$ docker service scale friendly=1

For efficient distribution, instead of docker hub, we deploy a registry service ourselves:

$ docker service create --name registry --publish 5555:5000 registry:2

See if it succeeds:

$ docker service ps registry

OK, let's push the friendly hello: V4 image to registry. Before that, let's create a configuration file and add the configuration. Otherwise, https-related problems may arise:

$ vi /etc/docker/daemon.json

Write in:

{"insecure-registries": ["<Your manager Of ip>:5555"]}

// My configuration:
{"insecure-registries": ["192.168.99.112:555"]}

Then restart docker:

$ sudo /etc/init.d/docker restart

After rebooting, we can retype the tag and push to register:

$ docker tag friendlyhello:v4 <Your manager Of ip>:5555/friendlyhello:v4
$ docker push <Your manager Of ip>:5555/friendlyhello:v4

# My orders:
$ docker tag friendlyhello:v4 192.168.99.112:5555/friendlyhello:v4
$ docker push 192.168.99.112:5555/friendlyhello:v4

If there's a weird problem here, try to wait a few seconds to re-execute it.

Next, go to worker-1 and worker-2 and add the same daemon.json:

$ vi /etc/docker/daemon.json

Don't forget to restart after adding the configuration

After restarting, we can pull down the mirror we need:

$ docker pull 192.168.99.112:5555/friendlyhello:v4
$ docker tag 192.168.99.112:5555/friendlyhello:v4 friendlyhello:v4

If there's another weird problem, try push ing again at the manager node

Then expand at the manager node:

$ docker service scale friendly=3

The task of the next three nodes succeeded in running:

$ docker service ps friendly

Visit through browser:

Deployment is no problem, but we also need to have it display the name of the node used, which requires adding environment variables.

First we shut down our current service:

$ docker service rm friendly

Recreate and add new parameters:

$ docker service create --replicas 3 -p 5000:5000 --name friendly3 -e HOSTNAME="{{.Node.Hostname}}" --hostname="{{.Node.Hostname}}-{{.Node.ID}}-{{.Service.Name}}" friendlyhello:v4

Come back and see:

STEP 5: Visualizing Swarm Cluster Management with Portainer

Back at the manager node, now deploy Portainer through docker stack:

$ curl -L https://downloads.portainer.io/portainer-agent-stack.yml -o portainer-agent-stack.yml
$ docker stack deploy --compose-file=portainer-agent-stack.yml portainer

Upon completion, we can access Portainer through port: 9000:

There are plenty of functions to make it easy for us to visually operate swarm clusters

Tags: Python Docker Redis ssh JSON

Posted on Wed, 04 Sep 2019 19:50:35 -0700 by jursten