ADG Оставить заявку
Блог DevOps 5 мин чтения

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 для чего-то постоянного - слишком новый инструмент, слишком мало понятно как он ведёт себя под длительной нагрузкой. Но для тестовых сред с коротким жизненным циклом - уже работает и экономит время.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.