MAATRIX / Блог / Тестировщику нужны пять окружений сразу: свой сервер вместо очереди

Тестировщику нужны пять окружений сразу: свой сервер вместо очереди

MAATRIX

Знакомая ситуация: нужно проверить баг сразу на трёх версиях приложения, ещё на двух конфигурациях базы — а общий тестовый стенд компании занят соседней командой до вечера. Вы пишете в чат «можно стенд?», ждёте, теряете час, потом ещё полчаса разбираетесь, что там осталось от чужого прогона. Если вы тестировщик — штатный или фрилансер, ведущий несколько проектов параллельно — решение простое и не требует согласований: свой сервер, на котором окружения поднимаете и сносите вы сами, столько, сколько нужно в моменте.

Почему общего стенда всегда не хватает

Тестирование редко идёт по одной версии приложения за раз. Типичная неделя тестировщика может выглядеть так:

  • регрессия на текущем релизе в проде-конфигурации;
  • проверка хотфикса на ветке, которую вот-вот зальют;
  • воспроизведение бага, который ловится только на старой версии БД;
  • смоук на конфиге для другого региона или тарифа;
  • параллельная проверка двух конкурирующих реализаций одной фичи перед код-ревью.

Каждая точка — это, по-хорошему, отдельное изолированное окружение: своя версия кода, свои данные, свои переменные окружения. На одном общем стенде так не сделать — тестировщики по очереди перезаливают на него то одну ветку, то другую, и результат зависит от того, кто последний деплоил. Отсюда классическое «стенд занят», очередь в календаре бронирования и потерянные часы, которые в отчёте времени превращаются в неловкое «ждал окружение».

Проблема не в квалификации QA-отдела, а в архитектуре: один физический или виртуальный стенд физически не может быть одновременно в пяти разных состояниях. Нужно либо пять стендов, либо способ быстро поднимать и сносить окружения по требованию.

Свой сервер вместо очереди за общим

Альтернатива — не выбивать у DevOps ещё один стенд, а взять под личный контроль небольшой сервер и поднимать на нём столько окружений, сколько нужно именно вам. Пять — это не магическое число, а иллюстрация: сегодня вам могут понадобиться две версии для регрессии и хотфикса, завтра — все пять для сравнительного тестирования конфигураций. Разница с корпоративным стендом принципиальная:

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

Для этого не нужен кластер серверов — обычно хватает одного VPS или выделенного сервера с достаточным запасом CPU и RAM, на котором окружения живут как отдельные Docker-контейнеры или лёгкие виртуальные машины. Дальше — как это собрать технически.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Как поднять пять окружений одновременно на одном сервере

Самый практичный вариант для веб-приложений — Docker Compose с профилями или просто с разными именами проектов. Идея: у вас один и тот же docker-compose.yml, но каждое окружение поднимается со своим префиксом контейнеров, своими портами и своей БД.

Каскадный вариант — один compose-файл, пять запусков с разным -p:

# окружение под регрессию текущего релиза
docker compose -p qa-release -f docker-compose.yml up -d

# окружение под хотфикс-ветку
docker compose -p qa-hotfix -f docker-compose.yml up -d

# окружение под старую версию БД для конкретного бага
docker compose -p qa-legacy-db -f docker-compose.yml up -d

Каждый -p создаёт свой namespace: свои контейнеры, свою сеть, свои volume — окружения не видят данные друг друга. Порты наружу лучше не хардкодить в compose-файле, а прокидывать через переменные:

services:
  app:
    image: myapp:${APP_TAG:-latest}
    ports:
      - "${APP_PORT:-8080}:8080"
    environment:
      - DATABASE_URL=postgres://qa:qa@db:5432/qa
  db:
    image: postgres:16
    volumes:
      - db_data:/var/lib/postgresql/data
volumes:
  db_data:

Тогда для пяти окружений просто задаёте разные APP_PORT и APP_TAG (версию образа или тег ветки) при запуске. Про сам механизм профилей и множественных окружений в одном compose-файле подробнее разобрано в статье про Docker Compose profiles для нескольких окружений — там же нюансы, когда лучше не плодить сервисы через профили, а держать отдельные compose-проекты, как в примере выше.

Если приложение тяжёлое или тестируете не веб-сервис, а что-то, что требует полноценной ОС (десктопное приложение через RDP, мобильный эмулятор, отдельное ядро) — вместо контейнеров разумнее лёгкие виртуальные машины на базе KVM или LXC-контейнеры. Здесь удобно держать одну «золотую» VM-заготовку с уже настроенным окружением и клонировать её под каждую задачу — подход и команды для этого разобраны в статье про клонирование виртуалок и шаблоны.

Изоляция: чтобы окружения не мешали друг другу

Пять окружений на одном сервере — это не только про пять процессов приложения, но и про то, чтобы они физически не пересекались:

Сеть. Каждый Docker Compose проект по умолчанию создаёт свою bridge-сеть, так что контейнеры разных окружений друг друга не видят напрямую — это работает «из коробки», просто не выносите порты БД наружу без необходимости. Если нужна более строгая сегментация (например, окружения разных заказчиков-фрилансеров должны быть недоступны друг другу даже теоретически), стоит развести их по отдельным Docker-сетям с явными правилами, а не полагаться только на дефолт.

Данные. У каждого окружения — свой volume с БД. Проблема в другом: тестовые данные быстро «протухают» после серии прогонов, и нужен способ быстро вернуть окружение в чистое состояние. Два рабочих подхода:

  • дамп эталонной БД и pg_restore/mysql < dump.sql перед стартом набора тестов;
  • снапшоты файловой системы, если диски на ZFS или LVM — тогда откат окружения к чистому состоянию занимает секунды, а не время на прогон миграций и сидов заново.
# пример со снапшотом ZFS-датасета под volume окружения
zfs snapshot tank/qa-hotfix@clean
# после серии тестов откатываем к чистому состоянию
zfs rollback tank/qa-hotfix@clean

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

Порты и адреса. Пять окружений с одинаковым набором сервисов на одном сервере рано или поздно упрутся в конфликт портов, если открывать их «в лоб». Практичнее поставить перед всеми reverse-proxy и раздавать окружения по поддоменам: hotfix.qa.example.com, legacy-db.qa.example.com и так далее — proxy сам маршрутизирует по имени хоста на нужный контейнер, а вам не нужно помнить, какой порт у какого окружения. Сравнение инструментов для этого — в статье Traefik или Nginx Proxy Manager: что выбрать для сервера.

Автоматизация подъёма и сноса окружений

Ручной запуск пяти docker compose up быстро надоедает, особенно если окружения нужны на час-два, а потом их надо снести, чтобы не занимали ресурсы. Здесь помогает простой скрипт-обёртка:

#!/usr/bin/env bash
# up-env.sh <name> <branch-or-tag> <port>
NAME=$1
TAG=$2
PORT=$3

APP_TAG=$TAG APP_PORT=$PORT docker compose -p "qa-$NAME" up -d
echo "Окружение $NAME поднято на порту $PORT (тег $TAG)"
./up-env.sh hotfix hotfix-branch-image 8081
./up-env.sh legacy-db v2.3-image 8082

А снос — так же коротко:

docker compose -p "qa-hotfix" down -v

Флаг -v удаляет и volume — то есть окружение сносится вместе с данными, и в следующий раз поднимается заново с чистого листа. Если вы тестируете код из системы контроля версий и хотите, чтобы окружение поднималось автоматически под каждый пуш в ветку — логичный следующий шаг: настроить CI-раннер прямо на этом же сервере, который по вебхуку собирает образ и поднимает или пересоздаёт нужное окружение. Как развернуть раннер и что учитывать при настройке — отдельная тема, здесь важно только то, что технически это тот же самый механизм docker compose -p, просто вызываемый не руками, а джобой CI.

Если окружений действительно пять и больше и вы их поднимаете часто, удобно завести реестр — обычный YAML или таблицу — с именем окружения, портом и назначением, чтобы через неделю не вспоминать, что за qa-legacy-db крутится на 8082 и можно ли его уже снести.

Сколько ресурсов закладывать и что это меняет по деньгам

Точную цифру потребления назвать нельзя — она зависит от того, что вы тестируете: лёгкий API и тяжёлый монолит с очередями и полнотекстовым поиском требуют совершенно разного объёма ресурсов. Но общая логика сайзинга такая:

  • считайте ресурсы на одно окружение так же, как считали бы для минимального прод-инстанса вашего приложения (реальные требования обычно уже описаны в документации проекта или видны по докер-образам);
  • умножайте на число окружений, которые реально держите одновременно поднятыми, а не на максимум, который теоретически можете захотеть — часть окружений большую часть времени можно держать погашенными и поднимать по требованию;
  • закладывайте запас на саму СУБД в каждом окружении — она обычно ест заметно больше памяти, чем сам тестируемый сервис.

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

Если тестовые окружения — это не веб-сервис, а полноценный сайт или CMS, для которого нужна честная копия боевого окружения с реальным контентом, а не синтетические данные — посмотрите, как устроена автоматическая синхронизация staging-копии сайта: тот же принцип «своя изолированная копия под рукой», но заточенный именно под контентные проекты.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Хватит ли обычного VPS или нужен выделенный сервер?

Для большинства сценариев — регрессия на нескольких версиях, хотфиксы, проверка конфигураций веб-приложения — достаточно VPS с несколькими ядрами и объёмом памяти, посчитанным по числу одновременно поднятых окружений. Выделенный сервер имеет смысл, если тестируете что-то ресурсоёмкое (нагрузочное тестирование, тяжёлые сборки, эмуляторы) или держите постоянно поднятыми много окружений сразу.

Что делать, если приложение тестируется не через Docker, а разворачивается вручную на голой ОС?

Тогда вместо Compose-проектов используйте отдельные виртуальные машины или LXC-контейнеры под каждое окружение, а «золотую» заготовку с уже настроенным окружением клонируйте под новую задачу — это быстрее, чем ставить всё с нуля каждый раз.

Как быстро вернуть окружение в чистое состояние после серии тестов, не пересобирая его?

Если диск под volume или VM на ZFS или LVM, используйте снапшоты файловой системы — откат к чистой точке занимает секунды. Без снапшотов — держите эталонный дамп БД и накатывайте его перед новым прогоном.

Не проще ли просто попросить у компании ещё один общий стенд?

Организационно — возможно, но это чужой ресурс с чужими приоритетами: его снова будут делить с другими, а согласование новой инфраструктуры занимает время. Свой сервер под личным контролем решает проблему быстрее и не зависит от чужого бюджета или очереди задач у DevOps.

Что будет, если забыть снести старое окружение?

Оно продолжит занимать ресурсы сервера — CPU, память, диск под volume. Если окружений становится много, стоит завести простое правило (или cron-задачу), которая сносит окружения старше определённого срока, либо вести список активных окружений вручную, чтобы не забывать о них.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →