Docker Machine 0.2: создаём Docker-хосты в облаке одной командой
Пробуем Docker Machine 0.2 для разворачивания тестовых сред на удалённых серверах. Один скрипт создаёт хост, ставит Docker и добавляет в Swarm-кластер.
Docker Machine 0.2 позволяет создавать Docker-хосты в облаке и на bare metal единой командой docker-machine create
В конце февраля Docker Inc. выпустила Docker Machine 0.2. Мы смотрели на первую версию ещё в preview и тогда отложили - было слишком сыро. 0.2 показался достаточно рабочим, чтобы попробовать на реальной задаче: быстрое создание тестовых сред на удалённых серверах.
Контекст такой. Несколько клиентских проектов используют Docker в CI-пайплайне для сборки и прогона тестов. Локально всё хорошо - Docker Compose закрывает dev-окружение. Но есть ещё задача: поднять изолированную тестовую среду на отдельном хосте - например, для нагрузочного тестирования или для QA-команды клиента, которая хочет потрогать конкретную ветку. Раньше это был ручной процесс: выдать хост, зайти по SSH, поставить Docker, настроить firewall, добавить в инвентарь.
Что такое Docker Machine
Docker Machine - это CLI-инструмент, который автоматизирует создание хоста с Docker. Один вызов docker-machine create создаёт виртуальную машину (или берёт физический сервер), ставит на неё Docker, настраивает TLS для Docker API и прописывает переменные окружения локально - так что после этого все локальные docker-команды уходят на удалённый хост.
Поддерживаемые провайдеры в 0.2 - DigitalOcean, Amazon EC2, Google Compute Engine, Microsoft Azure, VMware vSphere и несколько других. Для физических серверов или своих VM есть драйвер generic - нужны только SSH-доступ и sudo.
Как это выглядит в работе
Создать хост на DigitalOcean:
docker-machine create \
--driver digitalocean \
--digitalocean-access-token $DO_TOKEN \
--digitalocean-region ams3 \
--digitalocean-size 2gb \
testenv-feature-x
Через пару минут хост готов. После этого:
eval "$(docker-machine env testenv-feature-x)"
docker ps # уже смотрит на удалённый хост
docker-compose up -d # поднимает стек там же
Для физического сервера, где уже есть SSH-доступ:
docker-machine create \
--driver generic \
--generic-ip-address 10.0.1.50 \
--generic-ssh-user deploy \
testenv-bare
Machine сама заходит по SSH, ставит Docker через скрипт get.docker.com, настраивает TLS и возвращает готовый хост.
Скрипт для тестовых сред
Мы написали небольшой bash-скрипт, который оборачивает эту логику для нашего типового случая: создать хост, запустить стек, добавить в Swarm.
#!/bin/bash
set -e
NAME="testenv-${1:-$(date +%Y%m%d-%H%M)}"
DRIVER=${DRIVER:-generic}
echo "Создаём хост $NAME..."
docker-machine create \
--driver "$DRIVER" \
--generic-ip-address "${TARGET_IP}" \
--generic-ssh-user deploy \
"$NAME"
eval "$(docker-machine env "$NAME")"
echo "Разворачиваем стек..."
docker-compose -f docker-compose.test.yml up -d
if [ -n "$SWARM_MASTER" ]; then
echo "Добавляем в Swarm..."
TOKEN=$(docker run --rm swarm create)
docker run -d swarm join \
--addr="$(docker-machine ip "$NAME"):2375" \
"token://$TOKEN"
echo "Swarm token: $TOKEN"
fi
echo "Хост готов: $(docker-machine ip "$NAME")"
Вызов: TARGET_IP=10.0.1.51 SWARM_MASTER=1 ./create-testenv.sh feature-auth.
Итого: хост с Docker и запущенным стеком - минут за пять, если сервер уже есть и SSH настроен. Если сервер создаётся в облаке - чуть дольше, зависит от провайдера.
Что понравилось
TLS из коробки. Machine генерирует сертификаты и настраивает Docker daemon на приём только по TLS. Раньше это был отдельный шаг, который частенько пропускали на тестовых средах - "это же не продакшн". Теперь это ноль усилий.
docker-machine ls как инвентарь. Видно все созданные хосты, их статус, IP и версию Docker. Не замена нормальному инвентарю, но для пула тестовых сред - удобно.
docker-machine ssh. Зайти на хост без отдельного поиска ключей и IP: docker-machine ssh testenv-feature-x. Мелочь, но приятно.
Где спотыкаемся
Swarm в 0.2 - это ещё очень ранняя история. Инструкции из документации работают, но логика управления кластером через токены выглядит временным решением. Мы пробовали добавить три хоста в один Swarm и запустить контейнер - работает, но планировщик примитивный, никакого контроля над размещением нет.
Драйвер generic иногда ведёт себя странно если у целевого сервера нестандартный Python или старый curl. Скрипт установки Docker тянет зависимости через curl, и если что-то не так - получаешь криптическое сообщение об ошибке. Пришлось добавить в нашу стандартную подготовку серверов явную установку curl и ca-certificates через Ansible до передачи хоста Machine.
Нет встроенного способа передать provisioning-шаги после установки Docker. Хочешь настроить Docker daemon с кастомными флагами или добавить registry mirror - придётся делать отдельным шагом через docker-machine ssh или Ansible. В нашем скрипте это временно решено через дополнительный Ansible-плейбук, который гоняется после docker-machine create.
Про интеграцию в пайплайн
Основной смысл для нас - не заменить Ansible или систему провизионинга, а добавить быстрый путь именно для Docker-хостов. Ansible остаётся для управления конфигурацией и сервисами на постоянных серверах. Machine - для временных тестовых сред, которые живут день-два и удаляются через docker-machine rm.
В рамках интеграционных работ это уже закрывает несколько реальных сценариев: QA-среда под конкретную ветку, нагрузочный стенд, демо для клиента. Раньше на такое уходил час ручной работы, сейчас - пять минут и скрипт.
Пока мы не трогаем Machine для чего-то постоянного - слишком новый инструмент, слишком мало понятно как он ведёт себя под длительной нагрузкой. Но для тестовых сред с коротким жизненным циклом - уже работает и экономит время.