Docker Stack

Il comando docker stack è simile al comando docker compose: compie il deployment di un numero di servizi orchestrati, ma come servizi swarm anzichè locali.

I servizi sono specificati in un file di configurazione YAML, che può essere benissimo docker-compose.yml. La sintassi è quella della versione 3.

Non è richiesta la specifica di versione nel file di configurazione: se cìè viene generato un warning ma il file è accettato comunque. La presenza di una specifica di versione permette di creare un file docker-compose.yml accettabile sia da docker compose che da docker stack.

E' buona norma di debugging testare il nostro applicativo con docker compose prima di sottoporlo a docker stack.

Vi sono comunque alcune limitazioni organizzative da considerare nella preparazione di un docker-compose.yml.

Prima demo

Preparare lo scaffolding:

mkdir -p ~/swarm/stackdemo
cd ~/swarm/stackdemo

Un applicativo scritto in Python:

vi app.py
from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

@app.route('/')
def hello():
    count = redis.incr('hits')
    return 'Hello World! I have been seen {} times.\n'.format(count)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000, debug=True)

File di requisiti:

vi requirements.txt
flask
redis

Costruzione del Dockerfile:

vi Dockerfile
# syntax=docker/dockerfile:1
FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

File di specifiche compose/stack:

vi docker-compose.yml
  services:
    web:
      image: 127.0.0.1:5000/stackdemo
      build: .
      ports:
        - "8000:8000"
    redis:
      image: redis:alpine

Installiamo un registry locale sulla macchina host:

docker run -d -p 5000:5000 --restart=always --name registry -v ~/registry:/var/lib/registry registry

Inviamo l'immagine al registry locale della macchina host:

docker-compose push

Nella nostra organizzazione le immagini del registry locale sono mappate anche alla directory ~/registry.

Copiamo il file di specifiche alla directory ~/manager-tmp, che è mappata a /tmp del nodo manager:

cp docker-compose.yml ~/manager-tmp

Ora possiamo compiere il deploy dello stack su manager:

dk docker stack deploy --compose-file /tmp/docker-compose.yml stackdemo

Controlliamo l'avvenuto deploy con:

dk docker stack ls

e con

dk docker stack ps  stackdemo

Testiamo il funzionamento dal nodo manager del cluster:

dk curl http://localhost:8000

oppure da un altro nodo del cluster:

dk curl http://192.168.77.4:8000

oppure dalla macchina host

curl http://manager:8000

Rimozione dello stack:

dk docker stack rm stackdemo

Seconda demo

L'esercizio di postgres e pgadmin.

Prepparare lo scaffolding:

mkdir -p ~/swarm/pg
cd ~/swarm/pg

Preparare il docker-compose:

vi docker-compose.yml
version: '3'

services:
  postserver:
    image: myregistry.com:5000/postgres:12.2
    environment:
      POSTGRES_PASSWORD: "secret"
    ports:
      - "5432:5432"
    volumes:
      - /data:/var/lib/postgresql/data
    networks:
      postnet:


  pgadmin:
    image: myregistry.com:5000/dpage/pgadmin4
    environment:
      PGADMIN_DEFAULT_EMAIL: "mich@stormforce.ac"
      PGADMIN_DEFAULT_PASSWORD: "supersecret"
    ports:
      - "8000:80"
    depends_on:
      - postserver
    networks:
      postnet:

networks:
  postnet:
    name: postnet

Copiare il file nella directory condivisa:

cp docker-compose.yml ~/manager-tmp

Compiere il deployment dello stack:

dk docker stack deploy --compose-file /tmp/docker-compose.yml pg

Verificare connettendosi a postadmin.