Files
2026-07-13 21:36:47 +08:00

14 KiB
Raw Permalink Blame History

Docker 与容器

使用场景:在容器中运行 Playwright 测试,以获得可复现的环境、用于 CI 流水线,或使用一致的浏览器版本进行本地开发。当团队需要在不同机器上拥有相同的测试环境时,此模式必不可少。

快速参考

# 官方 Playwright Docker 镜像
docker pull mcr.microsoft.com/playwright:v1.52.0-noble     # Ubuntu 24.04,包含所有浏览器
docker pull mcr.microsoft.com/playwright:v1.52.0-jammy      # Ubuntu 22.04,包含所有浏览器

# 在容器中运行测试
docker run --rm -v $(pwd):/app -w /app mcr.microsoft.com/playwright:v1.52.0-noble \
  npx playwright test

# 检查你的 Playwright 版本(必须与镜像标签一致)
npx playwright --version

模式

模式 1:在官方镜像中运行测试

适用场景:快速、可复现的测试运行,无需构建自定义镜像。 不适用场景:需要应用服务(数据库、API)同时运行——改用 docker-compose。

# 运行所有测试
docker run --rm \
  -v $(pwd):/app \
  -w /app \
  mcr.microsoft.com/playwright:v1.52.0-noble \
  bash -c "npm ci && npx playwright test"

# 使用环境变量运行
docker run --rm \
  -v $(pwd):/app \
  -w /app \
  -e CI=true \
  -e BASE_URL=http://host.docker.internal:3000 \
  mcr.microsoft.com/playwright:v1.52.0-noble \
  bash -c "npm ci && npx playwright test"

# 运行并提取报告
docker run --rm \
  -v $(pwd):/app \
  -w /app \
  -v $(pwd)/playwright-report:/app/playwright-report \
  mcr.microsoft.com/playwright:v1.52.0-noble \
  bash -c "npm ci && npx playwright test"

模式 2:自定义 Dockerfile

适用场景:需要额外的系统依赖、预装的 npm 包,或仅包含特定浏览器的更小镜像。 不适用场景:官方镜像开箱即用。

# Dockerfile.playwright
FROM mcr.microsoft.com/playwright:v1.52.0-noble

WORKDIR /app

# 先复制包文件,以便更好地利用层缓存
COPY package.json package-lock.json ./
RUN npm ci

# 复制项目其余部分
COPY . .

# 默认命令
CMD ["npx", "playwright", "test"]
# 构建并运行
docker build -f Dockerfile.playwright -t my-e2e-tests .
docker run --rm my-e2e-tests

# 使用特定选项运行
docker run --rm my-e2e-tests npx playwright test --project=chromium

# 提取报告
docker run --rm -v $(pwd)/reports:/app/playwright-report my-e2e-tests

仅含 Chromium 的精简镜像:

# Dockerfile.playwright-chromium
FROM node:20-slim

# 仅安装 Chromium 依赖
RUN npx playwright install --with-deps chromium

WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .

CMD ["npx", "playwright", "test", "--project=chromium"]

模式 3Docker Compose 与应用栈

适用场景:测试需要完整的应用栈——Web 服务器、数据库、缓存以及 Playwright 一起运行。 不适用场景:测试针对远程环境(预发布/生产环境)运行——不需要本地服务。

# docker-compose.yml
services:
  # 被测应用
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=test
      - DATABASE_URL=postgresql://postgres:postgres@db:5432/test
      - REDIS_URL=redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started

  # 数据库
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: test
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
    tmpfs:
      - /var/lib/postgresql/data # 使用内存盘提升速度

  # 缓存
  cache:
    image: redis:7-alpine

  # Playwright 测试运行器
  e2e:
    image: mcr.microsoft.com/playwright:v1.52.0-noble
    working_dir: /app
    volumes:
      - .:/app
      - /app/node_modules # 阻止宿主机的 node_modules 覆盖容器内的
    environment:
      - CI=true
      - BASE_URL=http://app:3000
    depends_on:
      - app
    command: bash -c "npm ci && npx playwright test"
    profiles:
      - test # 仅通过以下命令启动:docker compose --profile test up
# 启动完整栈并运行测试
docker compose --profile test up --abort-on-container-exit --exit-code-from e2e

# 仅启动应用(用于本地开发)
docker compose up app

# 对已运行的服务栈运行测试
docker compose --profile test run --rm e2e npx playwright test

# 拆除所有资源
docker compose --profile test down -v

模式 4:从容器的容器中提取报告与 Trace

适用场景:容器测试完成后,需要在宿主机上获取测试产物(HTML 报告、trace、截图)。 不适用场景:CI 原生负责产物收集(GitHub Actions、GitLab 制品)。

# 方法 1:绑定挂载输出目录
docker run --rm \
  -v $(pwd):/app \
  -v $(pwd)/playwright-report:/app/playwright-report \
  -v $(pwd)/test-results:/app/test-results \
  -w /app \
  mcr.microsoft.com/playwright:v1.52.0-noble \
  bash -c "npm ci && npx playwright test"

# 方法 2:从已停止的容器中复制产物
docker run --name e2e-run \
  -v $(pwd):/app \
  -w /app \
  mcr.microsoft.com/playwright:v1.52.0-noble \
  bash -c "npm ci && npx playwright test" || true

docker cp e2e-run:/app/playwright-report ./playwright-report
docker cp e2e-run:/app/test-results ./test-results
docker rm e2e-run

# 查看报告
npx playwright show-report ./playwright-report

Docker Compose 报告提取:

# docker-compose.yml(添加到 e2e 服务)
services:
  e2e:
    image: mcr.microsoft.com/playwright:v1.52.0-noble
    working_dir: /app
    volumes:
      - .:/app
      - ./playwright-report:/app/playwright-report
      - ./test-results:/app/test-results
    # ... 其余配置

模式 5CI 容器策略

适用场景:你的 CI 环境受益于容器化的测试执行。

GitHub Actions —— 容器作业:

# .github/workflows/playwright.yml
jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: mcr.microsoft.com/playwright:v1.52.0-noble
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx playwright test
        env:
          HOME: /root

GitLab CI —— image 指令:

# .gitlab-ci.yml
test:
  image: mcr.microsoft.com/playwright:v1.52.0-noble
  script:
    - npm ci
    - npx playwright test

Jenkins —— Docker 代理:

// Jenkinsfile
pipeline {
    agent {
        docker {
            image 'mcr.microsoft.com/playwright:v1.52.0-noble'
            args '-u root'
        }
    }
    stages {
        stage('Test') {
            steps {
                sh 'npm ci'
                sh 'npx playwright test'
            }
        }
    }
}

模式 6:开发容器(devcontainer

适用场景:你的团队使用 VS Code 开发容器或 GitHub Codespaces,并且需要在开发环境中使用 Playwright。 不适用场景:每个人都在本地安装 Playwright,且版本差异不会引发问题。

// .devcontainer/devcontainer.json
{
  "name": "Playwright Dev",
  "image": "mcr.microsoft.com/playwright:v1.52.0-noble",
  "features": {
    "ghcr.io/devcontainers/features/node:1": {
      "version": "20"
    }
  },
  "postCreateCommand": "npm ci",
  "customizations": {
    "vscode": {
      "extensions": ["ms-playwright.playwright"]
    }
  },
  "forwardPorts": [3000, 9323],
  "remoteUser": "root"
}

决策指南

场景 方案 原因
简单 CI 流水线 将官方 Playwright 镜像作为 CI 镜像 浏览器已预装;零浏览器安装时间
测试需要数据库 + 缓存 使用 Docker Compose 提供 app、db、cache、e2e 服务 完整服务栈在隔离容器中运行
团队需要相同的环境 开发容器或自定义 Dockerfile 消除"在我机器上能跑"的问题
仅测试 Chromium 精简镜像:node:20-slim + install --with-deps chromium 镜像更小,拉取更快
跨浏览器测试 官方 Playwright 镜像(包含所有浏览器) 三大引擎已预装
本地开发 直接在宿主机上运行,不在容器中 迭代更快,调试更方便
需要提取产物的 CI 绑定挂载报告/结果目录,或使用 CI 制品上传 容器退出后报告仍可访问
镜像 大小 浏览器 基础操作系统
mcr.microsoft.com/playwright:v1.52.0-noble ~2 GB Chromium, Firefox, WebKit Ubuntu 24.04
mcr.microsoft.com/playwright:v1.52.0-jammy ~2 GB Chromium, Firefox, WebKit Ubuntu 22.04
自定义精简版(仅 Chromium ~800 MB Chromium 取决于基础镜像

反模式

反模式 问题 正确做法
镜像标签与 @playwright/test 版本不匹配 浏览器二进制文件与 Playwright 库不兼容 始终匹配:v1.52.0 镜像对应 @playwright/test@1.52.0
使用 latest 标签 不可预测;镜像更新可能破坏测试 锁定到确切版本:v1.52.0-noble
在容器运行时安装浏览器 每次运行浪费 60-90 秒 使用官方镜像(浏览器预装)或构建预装浏览器的自定义镜像
以非 root 用户运行且未配置沙箱 Chromium 沙箱因权限错误失败 以 root 运行(-u root)或在启动参数中禁用沙箱(--no-sandbox
从宿主机绑定挂载 node_modules 平台相关二进制文件(macOS vs Linux)导致崩溃 使用匿名卷:-v /app/node_modules
依赖服务没有健康检查 数据库就绪前测试就已启动 为 db 服务添加 healthcheck;使用 depends_on: condition: service_healthy
在 Playwright 容器内部构建应用 镜像庞大、构建缓慢、基础镜像不适合你的应用 在 docker-compose 中将应用和 e2e 容器分离

故障排除

容器中报错 "browserType.launch: Executable doesn't exist"

原因package.json 中的 Playwright 版本与 Docker 镜像版本不匹配。

修复:确保版本精确匹配:

# 检查你的版本
npm ls @playwright/test
# @playwright/test@1.52.0

# 使用匹配的镜像
docker pull mcr.microsoft.com/playwright:v1.52.0-noble

docker-compose 中测试失败,报错 "net::ERR_CONNECTION_REFUSED"

原因:测试尝试访问 localhost:3000,但应用在另一个容器中。

修复:使用服务名称作为主机名,并配置 baseURL

// playwright.config.ts
import { defineConfig } from "@playwright/test"

export default defineConfig({
  use: {
    baseURL: process.env.BASE_URL || "http://localhost:3000",
  },
  // 在 Docker 中禁用 webServer——应用由 docker-compose 管理
  ...(process.env.CI
    ? {}
    : {
        webServer: {
          command: "npm run dev",
          url: "http://localhost:3000",
          reuseExistingServer: true,
        },
      }),
})
# docker-compose.yml
e2e:
  environment:
    - BASE_URL=http://app:3000 # "app" 是服务名称

挂载卷权限被拒绝

原因:容器以 root 运行,但宿主机文件归你的用户所有,或反之。

修复:匹配用户 ID 或以 root 运行:

# 以宿主机用户身份运行
docker run --rm -u $(id -u):$(id -g) \
  -v $(pwd):/app -w /app \
  mcr.microsoft.com/playwright:v1.52.0-noble \
  npx playwright test

# 或以 root 运行(更简单,CI 中适用)
docker run --rm \
  -v $(pwd):/app -w /app \
  mcr.microsoft.com/playwright:v1.52.0-noble \
  npx playwright test

容器测试比本地慢得多

原因macOS/Windows 上的 Docker Desktop 对绑定挂载卷存在 I/O 开销。

修复:将文件复制到容器内部,而非挂载:

# Dockerfile.playwright
FROM mcr.microsoft.com/playwright:v1.52.0-noble
WORKDIR /app
COPY . .
RUN npm ci
CMD ["npx", "playwright", "test"]

或在 macOS 上使用 delegated 挂载:

docker run --rm \
  -v $(pwd):/app:delegated \
  -w /app \
  mcr.microsoft.com/playwright:v1.52.0-noble \
  bash -c "npm ci && npx playwright test"

相关文档