Тесты которые проходят локально но падают в CI чаще всего это не баги в тестах: причина в несоответствии окружений между версиями Node, сборками браузера или отсутствующими системными зависимостями. Docker-контейнер решает это упаковывая Playwright, его браузерные бинарники и все зависимости в единый образ который запускается идентично на ноутбуке, машине коллеги и CI. Здесь разобрано написание Dockerfile для Playwright, запуск тестов в контейнере локально, интеграция с GitHub Actions и использование Docker Compose когда тестам нужны приложение и база данных рядом.

Зачем QA-инженеру Docker

Без Docker

  • Тесты проходят локально на Node 20, падают в CI на Node 18
  • Версия Chrome в CI отличается от версии на ноутбуке
  • Переменные окружения настроены по-разному на каждой машине
  • Новый член команды тратит день на то чтобы запустить тесты

С Docker

Тесты запускаются в одном контейнере локально и в CI. Все используют одни версии Node, Chrome и зависимостей. Новый член команды: docker compose up, тесты запускаются за 2 минуты.

Основные концепции

Image (образ)

Образ: шаблон, read-only снимок файловой системы с установленным ПО. Как класс в коде.

mcr.microsoft.com/playwright:latest : образ с предустановленными Playwright и браузерами
node:20-alpine : Node.js 20 на минимальном Alpine Linux

Container (контейнер)

Контейнер: запущенный экземпляр образа. Из одного образа можно запустить несколько контейнеров одновременно. Как создание нескольких объектов из одного класса.

Dockerfile

Инструкции для создания собственного образа. Начинаешь с базового образа и добавляешь свои файлы и конфигурацию.

Docker Compose

Инструмент для запуска нескольких контейнеров вместе. Тестам может понадобиться работающий веб-сервер и база данных: Compose запускает всё это одной командой.

Первый Playwright Dockerfile

Playwright предоставляет официальные Docker-образы с предустановленными браузерами:

# Dockerfile
FROM mcr.microsoft.com/playwright:v1.44.0-jammy

# Рабочая директория внутри контейнера
WORKDIR /app

# Сначала копируем файлы зависимостей (оптимизация кеширования)
COPY package.json package-lock.json ./

# Устанавливаем Node-зависимости
RUN npm ci

# Копируем остальную часть проекта
COPY . .

# Команда по умолчанию: запуск всех тестов
CMD ["npx", "playwright", "test"]

Собрать образ

docker build -t my-playwright-tests .

Запустить тесты

docker run my-playwright-tests

Chrome, Firefox и WebKit уже внутри контейнера. Устанавливать браузеры на хост-машине не нужно.

Запуск тестов с Docker

Базовый запуск

# Запустить все тесты
docker run my-playwright-tests

# Запустить конкретный тестовый файл
docker run my-playwright-tests npx playwright test tests/login.spec.ts

# Запустить с переменной окружения
docker run -e BASE_URL=https://staging.myapp.com my-playwright-tests

# Примонтировать локальную директорию (чтобы видеть результаты тестов)
docker run -v $(pwd)/playwright-report:/app/playwright-report my-playwright-tests

Сохранение результатов тестов

Файловая система контейнера исчезает при его остановке. Используй монтирование томов для сохранения отчётов:

docker run \
  -v $(pwd)/playwright-report:/app/playwright-report \
  -v $(pwd)/test-results:/app/test-results \
  my-playwright-tests

После прогона playwright-report/ появится на локальной машине.

Docker Compose для полного стека

Реальное тестирование часто требует чтобы тестируемое приложение тоже работало. Compose запускает всё вместе.

# docker-compose.yml
version: '3.8'

services:
  # Тестируемое приложение
  app:
    image: myapp:latest
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=test
      - DATABASE_URL=postgresql://postgres:postgres@db:5432/testdb
    depends_on:
      db:
        condition: service_healthy

  # База данных
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: testdb
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  # Playwright-тесты
  tests:
    build: .
    environment:
      - BASE_URL=http://app:3000
    depends_on:
      - app
    volumes:
      - ./playwright-report:/app/playwright-report
      - ./test-results:/app/test-results

Запустить всё

docker compose up --exit-code-from tests

Запускает базу данных, ждёт пока она станет готовой, запускает приложение, прогоняет тесты, возвращает код выхода тестов (чтобы CI знал прошли или нет). --exit-code-from tests выходит с кодом выхода контейнера тестов.

Оптимизация Dockerfile

Кеширование слоёв ускоряет пересборку. Ключевое правило: то что меняется редко ставь выше.

FROM mcr.microsoft.com/playwright:v1.44.0-jammy

WORKDIR /app

# 1. Копируем файлы зависимостей (меняются редко)
COPY package.json package-lock.json ./
# Этот слой кешируется пока не изменится package.json
RUN npm ci

# 2. Копируем остальное (меняется с каждым коммитом)
COPY . .

CMD ["npx", "playwright", "test"]

Если изменились только тестовые файлы, Docker переиспользует слой npm ci из кеша. Время сборки: секунды вместо минут.

Интеграция с CI/CD

GitHub Actions

# .github/workflows/playwright.yml
name: Playwright Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Build test image
        run: docker build -t playwright-tests .
      
      - name: Run tests
        run: |
          docker run \
            -v ${{ github.workspace }}/playwright-report:/app/playwright-report \
            -e BASE_URL=${{ secrets.STAGING_URL }} \
            playwright-tests
      
      - name: Upload report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: playwright-report
          path: playwright-report/

GitLab CI

# .gitlab-ci.yml
test:
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t tests .
    - docker run 
        -v $(pwd)/playwright-report:/app/playwright-report
        -e BASE_URL=$STAGING_URL
        tests
  artifacts:
    when: always
    paths:
      - playwright-report/

Полезные Docker-команды для QA

# Список запущенных контейнеров
docker ps

# Список всех образов
docker images

# Остановить все запущенные контейнеры
docker stop $(docker ps -q)

# Удалить все остановленные контейнеры
docker container prune

# Удалить неиспользуемые образы
docker image prune

# Следить за логами контейнера
docker logs -f <container-id>

# Открыть shell внутри запущенного контейнера (полезно для отладки)
docker exec -it <container-id> /bin/bash

# Запустить контейнер в интерактивном режиме
docker run -it my-playwright-tests /bin/bash

Отладка внутри контейнера

Когда тесты падают только в контейнере:

# Запустить контейнер с shell вместо тестов
docker run -it my-playwright-tests /bin/bash

# Теперь ты внутри контейнера
# Проверить что установлено
node --version
npx playwright --version

# Запустить тесты вручную
npx playwright test tests/login.spec.ts --headed --debug

# Проверить переменные окружения
env | grep BASE_URL

Частые проблемы: BASE_URL указывает на localhost (работает на хосте, падает в контейнере: используй имя сервиса); отсутствующие переменные окружения; права на файлы (файлы созданные вне контейнера могут принадлежать root внутри).

Официальный Docker-образ Playwright

# Скачать последний образ Playwright
docker pull mcr.microsoft.com/playwright:v1.44.0-jammy

# Посмотреть что внутри
docker run -it mcr.microsoft.com/playwright:v1.44.0-jammy /bin/bash

# Проверить установленные браузеры
npx playwright install --list

Теги которые нужно знать: v1.44.0-jammy (конкретная версия Playwright на Ubuntu 22.04) и latest (последняя версия, может ломаться при обновлении). Всегда фиксируй конкретную версию в production.

Сводная таблица

| Концепция | Что это |

|-----------|---------|

| Image (образ) | Шаблон с предустановленным ПО |

| Container (контейнер) | Запущенный экземпляр образа |

| Dockerfile | Инструкции для создания образа |

| Docker Compose | Запуск нескольких контейнеров вместе |

| Volume mount | Общий доступ к файлам между хостом и контейнером |

Для Playwright конкретно:

1. Используй mcr.microsoft.com/playwright как базовый образ: браузеры уже включены

2. Монтируй директории с отчётами чтобы результаты не исчезали при остановке контейнера

3. Используй Compose для совместного запуска приложения и тестов

4. Фиксируй версии образов: latest приводит к неожиданным поломкам

Docker превращает «работает на моей машине» в «работает везде». Для QA это означает что тесты реально тестируют ПО, а не борются с различиями окружений.

→ See also: Docker для тестировщиков: запуск Playwright в контейнерах | CI/CD для QA: сравнение GitHub Actions, Jenkins и GitLab | GitHub Actions для тестов Playwright: полная настройка (2026)