Как мы отказались от Docker для on-prem деплоймента

Все начиналось очень радужно, когда мы проектировали серверную часть одного проекта для on-prem установки. На тот момент выбор способа развертывания казался очевидным: публикуем Docker-образ, клиенту шлем скрипт для деплоя, ну а дальше — стандартный docker pull и запуск. И вроде это выглядело логичным и правильным подходом: изоляция, повторяемость окружения, одна и та же команда для любой ОС. Ибо сам проект не сильно замороченный - простой бекенд, одна база без необходимости репликации и всей этой магии с надежностью и доступностью. Однако... план продержался до первой реальной установки.

Момент истины На демо для инвестора были две Windows-машины. И вот тут наш план забуксовал прямо на входе: Docker Desktop на Windows не захотел заводиться от слова совсем — ему нужна включённая виртуализация (Hyper-V или WSL2). На этих конкретных машинах она не была настроена, и завести её сходу не получилось.

И вроде бы - проблема не в коде, не в образах, сама платформа собрана, протестирована и готова к работе. Да и проблема с псевдо-серверами была решаема - мы могли пойти в биос, настроить виртуализацию и так далее, довести все это до победного конца.

НО

Все это указывало на то, что дальнейшие поставки реальным клиентам потребуют непосредственного участия разработчиков, а этого нам как раз хотелось избежать по максимуму. Понятное дело, что полностью исключить не получилось бы, но хотелось минимизировать.

Момент принятия Нам пришлось признать, что это не разовая случайность, а системный риск. Если у первого же клиента (причём инвестора — то есть в максимально благоприятных для нас условиях) виртуализация не завелась сходу, где гарантия, что у следующего клиента будет иначе? On-prem означает, что мы не выбираем IT-окружение — оно уже есть, со своими ограничениями, историей и возможно IT-отделом, который может быть далеко не всегда отзывчивым.

А мы пойдем другим путем К счастью, серверная часть написана на Go. Поэтому решилипереписать в нативное Windows-приложение. Postgres тоже перестал быть контейнером: теперь это обычная нативная установка на машине клиента. Поменялся только способ доставки и запуска: вместо контейнера, требующего дополнительный слой виртуализации, — процесс, который ставится и работает напрямую на Windows-машине как системная служба.

Чего это стоило Убрав Docker, мы автоматически убрали и всё, что он давал бесплатно: единый механизм обновления, одинаковый для любой ОС (пересобрал образ — перезапустил контейнер), изоляцию процессов и зависимостей, предсказуемую воспроизводимость окружения.

Взамен нужно было придумывать свой механизм обновления ПО — уже не через пересоздание контейнера, а через замену бинарника Windows-службы и её перезапуск, с отдельным вниманием к миграциям базы данных без привычной контейнерной изоляции. Это оказалось отдельной содержательной задачей — и о ней стоит рассказать отдельно.

Вывод Docker — это отличное решение для проблемы изоляции и повторяемости, но оно не бесплатное: оно добавляет зависимость на слой виртуализации, который живёт ниже вашего приложения и вне вашего контроля. Для облачного деплоя это почти всегда приемлемая цена. Для on-prem продукта, который должен встать на машину с непредсказуемым IT-окружением клиента, это может стать точкой отказа — причём в самый неудобный момент, на глазах у инвестора. Иногда лёгкость установки у клиента важнее, чем «правильный» с точки зрения индустрии стек.