MEAN-stack и Docker. Часть 5 - Mongo Replica Set в Docker Swarm
Пятая часть цикла, посвященного контейнеризации MEAN-stack приложений, в которой мы развернем MongoDB Replica Set из трех узлов в Docker Swarm.
Содержание цикла
- Часть 1 - Dockerfile, образы, контейнеры
- Часть 2 - Docker Compose
- Часть 3 - Traefik reverse proxy
- Часть 4 - Docker Swarm
- Часть 5 - Mongo Replica Set в Docker Swarm
Введение
В предыдущей части мы задеплоили приложение в Docker Swarm. Однако сервис базы данных у нас не был реплицирован. В данной статье исправим это досадное недоразумение и развернем 3 реплики базы данных на нодах нашего Docker-роя. Но с репликацией mongo есть небольшая сложность - нельзя просто указать в compose-файле replicas: 3
. В случае падения одной из рабочих нод докер перенесет сервис mongo на ноду, где такой сервис уже есть. И эти сервисы начнут работать с общей data/db
. Но это недопустимо. Поэтому предстоит провести небольшую настройку.
Маркируем ноды
Каждой ноде укажем label с требуемым id реплики mongo. Для этого на менеджере выполним следующие команды:
docker node update --label-add mongo.replica=0 vm0
docker node update --label-add mongo.replica=1 vm1
docker node update --label-add mongo.replica=2 vm2
Настроим сервисы
В compose-файле вместо сервиса db
создадим 3 других:
services:
# ...
mongo0:
image: mongo
command:
- "--smallfiles"
- "--replSet"
- "rs0"
deploy:
mode: global
restart_policy:
condition: on-failure
placement:
constraints:
- node.labels.mongo.replica == 0
labels:
- traefik.enable=false
volumes:
- mongodata0:/data/db
networks:
- db-net
mongo1:
image: mongo
command:
- "--smallfiles"
- "--replSet"
- "rs0"
deploy:
mode: global
restart_policy:
condition: on-failure
placement:
constraints:
- node.labels.mongo.replica == 1
labels:
- traefik.enable=false
volumes:
- mongodata1:/data/db
networks:
- db-net
mongo2:
image: mongo
command:
- "--smallfiles"
- "--replSet"
- "rs0"
deploy:
mode: global
restart_policy:
condition: on-failure
placement:
constraints:
- node.labels.mongo.replica == 2
labels:
- traefik.enable=false
volumes:
- mongodata2:/data/db
networks:
- db-net
В командах указываем запускать mongo как replica set с именем rs0
. В deploy
указываем глобальный режим mode: global
и задаем constraints-правило node.labels.mongo.replica == 0
, т.е. запускать mongo0
только на ноде с меткой mongo.replica=0
.
У сервера изменим путь для подключения mongoose к базе данных:
server:
...
environment:
- "db:uri=mongodb://mongo0,mongo1,mongo2/docker?replicaSet=rs0"
В конфиге других сервисов ничего не меняется (см. предыдущую часть цикла).
Volumes
Для хранения баз данных создадим следующие volumes:
volumes:
mongodata0:
mongodata1:
mongodata2:
и используем их в сервисах mongo
:
mongo0:
...
volumes:
- mongodata0:/data/db
Deploy
docker stack deploy -c docker-stack.mongo-rs.yml meanstack
Инициируем Replica Set в самой mongo
docker exec -it <mongo_container_id> sh
> mongo
> rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "mongo0:27017" },
{ _id: 1, host: "mongo1:27017" },
{ _id: 2, host: "mongo2:27017" }
]
})
Результат
В браузере по адресу http://visualizer.docker-example.local/ мы должны увидеть что-то похожее: