DEV Community

Reishi Mitani
Reishi Mitani

Posted on

Tutorial with Docker Swarm and Stack

Objectives

We will

  1. Create a docker image and push it to docker hub
  2. Pull the image from the hub and create a stack.

Procedures

First I created a directory as below.

$ mkdir docker-stack-tutorial
Enter fullscreen mode Exit fullscreen mode

We will create the Dockerfile, and some python scripts.
The directory should look like below.

$ tree
.
├── Dockerfile
├── app.py
└── requirements.txt

0 directories, 3 files
Enter fullscreen mode Exit fullscreen mode

The dockerfile is as below.

# Dockerfile

FROM python:3.7

WORKDIR /app

ADD . /app

RUN pip install -r requirements.txt

EXPOSE 80

ENV NAME World

CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

app.py for python is written as below.

# 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 = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv('NAME', "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

Enter fullscreen mode Exit fullscreen mode

Finally, the requirements.txt is:

# requirements.txt
Flask
Redis
Enter fullscreen mode Exit fullscreen mode

Now we will build and run the docker image.

$ docker build -t python-server .
Sending build context to Docker daemon   5.12kB
Step 1/7 : FROM python:3.7
 ---> 5c1cd4638fb7
............

$ docker run -p 4000:80 python-server
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
Enter fullscreen mode Exit fullscreen mode

Go to localhost:4000 and you should see this page (For some reason, redis was not working.):

Alt Text

We see that the container id is 99f360ce0c36 here. We will commit the image, and push it to docker hub.

$ docker login
Authenticating with existing credentials...
Login Succeeded

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                  NAMES
99f360ce0c36        python-server       "python app.py"     About a minute ago   Up About a minute   0.0.0.0:4000->80/tcp   keen_galois

$ docker commit 99f360ce0c36 python-server:latest
sha256:9dbcf7df033bb595c6e4c6528dd125716f11355d43dcea4dc8ccbaaced38c44c

$ docker tag python-server:latest USERNAME/python-server:latest

$ docker push USERNAME/python-server:latest
Enter fullscreen mode Exit fullscreen mode

Now we will create our docker-compose.yml file.

version: "3"
services:
  web:
    image: USERNAME/python-server:latest
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "80:80"
    networks:
      - webnet
networks:
  webnet:
Enter fullscreen mode Exit fullscreen mode

We will initialize the swarm and deploy it.

$ docker swarm init
Swarm initialized: current node (nrgwdwv97ioguu0gqq7t19kln) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-3lcxtiaau24gw21h2bgkd1ptavl56yczedbcm7d4e865naj8ks-7c5sgf7jh4youa7xsq2l3dt3j 192.168.65.3:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

$ docker stack deploy -c docker-compose.yml getstartedexample
Creating network getstartedexample_webnet
Creating service getstartedexample_web
Enter fullscreen mode Exit fullscreen mode

We can see all the nodes here using ps.

$ docker stack ps getstartedexample
ID                  NAME                      IMAGE                                  NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
x3xradislkhr        getstartedexample_web.1   USERNAME/python-server:latest   docker-desktop      Running             Running 12 seconds ago
shlygtlq66e0        getstartedexample_web.2   USERNAME/python-server:latest   docker-desktop      Running             Running 12 seconds ago
uk1wexhimc8a        getstartedexample_web.3   USERNAME/python-server:latest   docker-desktop      Running             Running 12 seconds ago
rijovk7yzr48        getstartedexample_web.4   USERNAME/python-server:latest   docker-desktop      Running             Running 12 seconds ago
avlqa3hxgbt2        getstartedexample_web.5   USERNAME/python-server:latest   docker-desktop      Running             Running 12 seconds ago

Enter fullscreen mode Exit fullscreen mode

When you access localhost, you should see the node ids every time you refresh.

Alt Text

Alt Text

Use the command below to exit.

$ docker stack rm getstartedexample
Removing service getstartedexample_web
Removing network getstartedexample_webnet
Enter fullscreen mode Exit fullscreen mode

Top comments (0)