Docker Playwright UI Mode XServer Issue - Need Solution

Hey everyone! I need help with a Docker setup problem.

My situation: I want to run Playwright tests with the UI visible (headless set to false) inside a Docker container on my Cloud Linux server.

The error I keep getting: “Looks like you launched a headed browser without having a XServer running. Set either ‘headless: true’ or use ‘xvfb-run ’ before running Playwright.”

My setup:

docker-compose.yml:

version: "3.9"

services:
  playwright-tests:
    build: .
    volumes:
      - .:/workspace
    working_dir: /workspace
    command: npx playwright test specs/login.spec.js --ui

Dockerfile:

FROM node:20-bookworm

RUN npx -y [email protected] install --with-deps

WORKDIR /workspace

COPY package.json package-lock.json* ./
RUN npm ci

COPY . .

CMD ["npx", "@playwright/test", "test", "--reporter=html"]

login.spec.js:

import { chromium } from 'playwright';

const userEmail = '[email protected]';
const userPass = 'secret456';
const authPath = './storage/session-data.json';

const browserInstance = await chromium.launch({ headless: true });
const browserContext = await browserInstance.newContext();
const currentPage = await browserContext.newPage();

try {
  await currentPage.goto('https://www.example-site.com/signin');
  await currentPage.waitForTimeout(5000);

  await currentPage.waitForSelector('input[name="email"]', { state: 'visible', timeout: 8000 });
  await currentPage.waitForSelector('input[name="password"]', { state: 'visible', timeout: 8000 });

  await currentPage.fill('input[name="email"]', userEmail);
  await currentPage.fill('input[name="password"]', userPass);
  await currentPage.click('input[type="submit"]');
  await currentPage.waitForTimeout(5000);
  await browserContext.storageState({ path: './storage/session-data.json' });
  console.log('Authentication saved to:', authPath);
} catch (err) {
  console.error('Login process failed:', err);
} finally {
  await browserInstance.close();
}

I tried AI suggestions but they make the container freeze. Anyone know how to fix this XServer issue? Thanks!

Had this exact problem debugging Playwright on my VPS. You’re running headed browsers without a display server.

Here’s the fix: Add ENV DISPLAY=:99 and RUN apt-get update && apt-get install -y xvfb to your Dockerfile. Then wrap your command like this: xvfb-run -s "-screen 0 1920x1080x24" npx playwright test specs/login.spec.js --ui

Make sure you set headless: false in your test code - otherwise UI mode won’t work.

Hit this same issue 6 months ago debugging Playwright tests visually on a headless server. Your cloud Linux server doesn’t have a display server running - that’s what headed browser mode needs. Fixed it by installing Xvfb (X Virtual Framebuffer) in my Dockerfile. Add this after your FROM statement: RUN apt-get update && apt-get install -y xvfb then change your docker-compose command to: command: xvfb-run --auto-servernum --server-args='-screen 0 1024x768x24' npx playwright test specs/login.spec.js --ui. This creates a virtual display Playwright can use without needing an actual monitor. Set headless to false in your test file since you want UI mode. Container shouldn’t freeze with this setup.

Had this exact problem last month debugging test failures remotely. You’re trying to display a GUI app on a server with no display capability. Here’s what worked for me: modify your Dockerfile to include X11 packages and set up a virtual display. Add RUN apt-get update && apt-get install -y xvfb x11-utils to your Dockerfile. Then update your docker-compose command to xvfb-run -a -s "-screen 0 1280x1024x16" npx playwright test specs/login.spec.js --ui. The -a flag finds an available display number automatically, preventing conflicts. Also change headless: true to headless: false in your test since you want the UI visible. This gives you a virtual framebuffer that Playwright can render to without needing an actual graphical environment.