CI/CD с Docker

Использование Puppeteer в автоматизированном тестировании предоставляет возможность управлять браузером Chromium или Chrome программно, что делает его мощным инструментом для end-to-end тестов веб-приложений. Для стабильного выполнения тестов в различных окружениях и интеграции с процессами непрерывной интеграции (CI) необходимо использовать Docker. Это обеспечивает одинаковую среду для локальной разработки, сборки и CI-пайплайнов.


Создание Docker-образа для Puppeteer

Для Puppeteer критически важно, чтобы браузерная среда была корректно установлена. Chromium требует наличия определённых библиотек и шрифтов. Стандартный Node.js-образ недостаточен для корректного запуска тестов.

Пример Dockerfile:

FROM node:20-bullseye


RUN apt-get update && apt-get install -y \
    gconf-service \
    libasound2 \
    libatk1.0-0 \
    libc6 \
    libcairo2 \
    libcups2 \
    libdbus-1-3 \
    libexpat1 \
    libfontconfig1 \
    libgcc1 \
    libgconf-2-4 \
    libgdk-pixbuf2.0-0 \
    libglib2.0-0 \
    libgtk-3-0 \
    libnspr4 \
    libnss3 \
    libpango-1.0-0 \
    libx11-6 \
    libx11-xcb1 \
    libxcb1 \
    libxcomposite1 \
    libxcursor1 \
    libxdamage1 \
    libxext6 \
    libxfixes3 \
    libxi6 \
    libxrandr2 \
    libxrender1 \
    libxss1 \
    libxtst6 \
    ca-certificates \
    fonts-liberation \
    lsb-release \
    wget \
    xdg-utils \
    --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*

# Установка Puppeteer
WORKDIR /app
COPY package*.json ./
RUN npm install --only=production
COPY . .

# Переменные окружения для безголового режима
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=false
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium

CMD ["node", "test-runner.js"]

Особенности:

  • Установка библиотек через apt-get предотвращает ошибки запуска Chromium.
  • PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=false гарантирует загрузку встроенного Chromium.
  • Образ базируется на стабильной версии Node.js (node:20-bullseye), что обеспечивает предсказуемость зависимостей.

Настройка CI/CD пайплайна

В интеграции с CI/CD, например GitHub Actions, GitLab CI или Jenkins, Docker позволяет запускать тесты в изолированной среде.

Пример GitHub Actions workflow:

name: Puppeteer Tests

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      docker:
        image: docker:20.10.16
        options: --privileged

    steps:
      - uses: actions/checkout@v3

      - name: Build Docker Image
        run: docker build -t puppeteer-test .

      - name: Run Puppeteer Tests
        run: docker run --rm puppeteer-test

Пояснения:

  • Изоляция в контейнере исключает влияние локальных настроек системы CI.
  • Можно использовать кеширование node_modules через Docker layer caching для ускорения сборок.
  • Встроенный Chromium запускается в headless-режиме, что обеспечивает детерминированные результаты тестов.

Конфигурация Puppeteer для CI

Для корректной работы Puppeteer в Docker необходимо учитывать headless-режим и флаги запуска Chromium:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: true,
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '--disable-dev-shm-usage',
      '--disable-accelerated-2d-canvas',
      '--no-zygote',
      '--single-process'
    ],
  });

  const page = await browser.newPage();
  await page.goto('https://example.com');
  console.log(await page.title());
  await browser.close();
})();

Ключевые моменты:

  • –no-sandbox и –disable-setuid-sandbox обязательны для CI, где контейнеры могут работать без прав root.
  • –disable-dev-shm-usage предотвращает переполнение /dev/shm в Docker-контейнерах.
  • headless: true уменьшает потребление ресурсов и исключает необходимость графического интерфейса.

Управление зависимостями и версиями Chromium

Использование фиксированной версии Puppeteer гарантирует стабильность тестов. Для этого в package.json указывают конкретную версию:

{
  "dependencies": {
    "puppeteer": "21.3.0"
  }
}

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

ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium

Это особенно важно при интеграции с CI/CD, чтобы тесты не ломались при обновлении Puppeteer или Chromium.


Логирование и отчётность в CI

Для диагностики сбоев важно сохранять скриншоты и видео тестовых сессий:

await page.screenshot({ path: 'screenshot.png', fullPage: true });

Можно добавить интеграцию с Allure или другими инструментами отчётности, чтобы при падении тестов CI отображал подробные результаты.


Масштабирование тестов

Docker позволяет запускать параллельные контейнеры для тестов:

docker run --rm puppeteer-test &
docker run --rm puppeteer-test &
wait

В CI это позволяет значительно ускорить выполнение тестов при большом количестве end-to-end сценариев.


Рекомендации по оптимизации

  • Кэширование слоёв Docker: использовать COPY package*.json ./ перед npm install, чтобы не пересобирать зависимости при каждом изменении кода.
  • Минимизация образа: удалять лишние пакеты и кэш apt (rm -rf /var/lib/apt/lists/*) для уменьшения размера образа.
  • Мониторинг ресурсов: Puppeteer в Docker может потреблять значительное количество RAM, особенно при параллельных сессиях, поэтому важно настраивать лимиты контейнеров.

Puppeteer в связке с Docker обеспечивает детерминированное и воспроизводимое выполнение тестов, полностью контролируемое CI/CD пайплайном. Использование изолированного контейнера устраняет проблемы различий окружений и позволяет масштабировать тесты на нескольких машинах без конфликта зависимостей.