MEAN-stack и Docker. Часть 4 - Docker Swarm

Четвертая часть цикла, посвященного контейнеризации MEAN-stack приложений, в которой приложение мы разворачиваем в кластере Docker Swarm.

Содержание цикла

Введение

Docker позволяет объединить в кластер группу машин, на которых он установлен. Этот кластер называется Swarm (рой). После этого можно выполнять все те же команды Docker, но теперь они будут выполняться в кластере swarm-менеджером. Помимо менеджеров в swarm могут быть и воркеры (workers). Все машины, подключенные к swarm, называются нодами (nodes). Менеджеры также отвечают и за распределение сервисов между всеми нодами. Правила распределения и взаимодействия сервисов описываются в уже известном нам docker-compose YAML-файле. Совокупность всех сервисов в swarm носит название stack.

Создаем машины

Для начала нужно заиметь группу машин.

Под виндой 3 виртуальные машины можно создать следующим образом:

docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" vm0
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" vm1
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" vm2

Как настроить Hyper-V >>

Под Mac/Linux:

docker-machine create --driver virtualbox vm0

Если хочется поиграться в условиях, приближенных к боевым, то можно поднять машины на дроплетах Digital Ocean:

docker-machine create --driver digitalocean --digitalocean-access-token xxxxx vm0
...

Пример c Digital Ocean Docker Machine >>

Посмотреть список доступных машин:

docker-machine ls

Инициируем Swarm-режим

Получим команды, которые настроят текущий shell для работы с демоном Docker на виртуальной машине:

docker-machine env vm0

Будет выведен список команд для текущей оболочки, которые нужно выполнить. В списке машин (docker-machine ls) в колонке ACTIVE символом * будет отмечена активная машина. Теперь все команды docker ... будут выполняться на ней.

Для инициации swarm-режима выполняем:

docker swarm init

В ответе будет указано, что текущая машина теперь менеджер. Также будет выведена команда для подключения к swarm рабочих нод.

Подключаем рабочие (worker) ноды

Переключаемся на другую машину и выполняем на ней предоставленную ранее команду:

docker-machine env vm1
...
docker swarm join --token SWMTKN-1-52qk72ooyql1zfxb0lezwmj52oipimmgln6zh3skbdokl6pp3c-179u2zzjdffcaqjni4zjst188 192.168.2.36:2377

Эту же процедуру проведем и с vm2.

Подключение менеджеров

Для подключения к swarm других менеджеров нужно запросить соответствующий токен:

docker swarm join-token manager

Docker Stack

Теперь у нас есть кластер на Docker Swarm, готовый к деплою нашего приложения. Однако приложение осталось чутка подготовить к запуску.

Stack - это, по сути, тот же docker-compose файл, но есть небольшие отличия. Так убираем из файла все depends_on - в swarm они не работают. Все сервисы запускаются параллельно и независимо. Поэтому на сервере пришлось настроить reconnect к базе данных в случае неудачи. Сервис может быть запущен до запуска базы данных, и тогда он уходит в цикл "падение-запуск" и, тем самым, солидно так грузит весь стек.

У сервисов добавляется раздел deploy, в котором настраиваются:

  • restart_policy (condition: on-failure);
  • update_config (parallelism: 2);
  • число экземпляров сервиса (replicas: 3);
  • правила размещения сервиса (placement constraints, preferences)
  • и ряд других параметров

Также в секцию deploy необходимо перенести все lebels.

Для стека создадим новый файл:

docker-stack.yml

version: "3.5"

services:

  server:
    image: myusername/public:mean-docker-server
    deploy:
      replicas: 2
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == worker
      labels:
        - traefik.docker.network=traefik-net
        - traefik.frontend.rule=Host:api.docker-example.local
        - traefik.port=3000
    environment:
      - "db:uri=mongodb://db/docker"
    networks:
      - traefik-net
      - db-net


  client:
    image: myusername/public:mean-docker-client
    deploy:
      replicas: 2
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == worker
      labels:
        - traefik.frontend.rule=Host:docker-example.local
        - traefik.port=4000
    networks:
      - traefik-net

  db:
    image: mongo
    command:
      - "--smallfiles"
    deploy:
      mode: global
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == manager
      labels:
        - traefik.enable=false
    networks:
      - db-net


  reverse-proxy:
    image: traefik
    command:
      - "--api"
      - "--entrypoints=Name:http Address::80"
      - "--defaultentrypoints=http"
      - "--docker"
      # Включаем режим Swarm
      - "--docker.swarmMode"
      - "--docker.domain=docker-example.local"
      - "--docker.watch"
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
      labels:
        - traefik.frontend.rule=Host:traefik.docker-example.local
        - traefik.port=8080
    ports:
      - 80:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      traefik-net:
        aliases:
          - api.docker-example.local

Запустим по 2 реплики "server" и "client". В placement:constraints указываем, что запускать их требуется только на воркерах (node.role == worker).

Для сервисов "db" и "reverse-proxy" укажем mode: global (запускать по 1 сервису на каждую ноду) и node.role == manager в constraints (только на менеджерах).

Docker Swarm Visualizer

Также в сервисы добавим визуализатор работы Swarm.

services:

  ...

  visualizer:
    image: dockersamples/visualizer:stable
    deploy:
      placement:
        constraints:
          - node.role == manager
      labels:
        - traefik.frontend.rule=Host:visualizer.docker-example.local
        - traefik.port=8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - traefik-net

Hosts

Заменим/добавим наши фейковые домены:

# windows:    c:/windows/system32/drivers/etc/hosts
# ubuntu/mac: /etc/hosts

192.168.2.40       docker-example.local
192.168.2.40       api.docker-example.local 
192.168.2.40       traefik.docker-example.local
192.168.2.40       visualizer.docker-example.local

Здесь 192.168.2.40 - IP-адрес менеджера (vm0). Узнать его можно с помощью docker-machine ls.

Deploy

Для развертывания приложения переключаемся на ноду-менеджер:

docker-machine env vm0
...

Создаем сеть:

docker network create -d overlay traefik-net

и выполняем деплой:

docker stack deploy -c docker-stack.yml meanstack

В браузере по адресу http://visualizer.docker-example.local/ мы должны увидеть какую-то такую картину:

В следующей части попробуем зареплицировать нашу базу данных.

Код проекта на GitHub >>

Часть 5 - Mongo Replica Set в Docker Swarm >>

Павел Прудников

Постигающий дзен фулстэк вэб буддизма

Минск, Беларусь

Подписаться на Блог MEAN stack разработчика

Получайте свежие записи прямо на ваш почтовый ящик.

Или подпишитесь на RSS с Feedly!

Комментарии

comments powered by Disqus