6

I'm attempting to figure out how to open a headed browser to do some tasks from inside of NestJs application running in a docker container.

Application Code:

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
import { chromium } from "playwright";

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  async getHello(): Promise<string> {
    const browser = await chromium.launch({ 
      headless: false,
      env: {
        "DISPLAY": ":99"
      }
    });
    const context = await browser.newContext({ javaScriptEnabled: true });
    const page = await context.newPage();

    await page.goto("http://www.google.com");
    await page.waitForLoadState("load");

    return "Yay";
  }
}

Dockerfile:

FROM ubuntu:20.04 AS BUILD_IMAGE

# INSTALL NODE
RUN apt-get update && apt-get install -y \
curl
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
RUN apt-get install nodejs -y

ENV NODE_ENV production

# Set up our work directory again
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

# copy the source code to build the next
# server for production
COPY . .

RUN npm run build

# Remove all the development dependencies since we don't
# need them to run the actual server.
RUN rm -rf node_modules
RUN npm ci --production --ignore-scripts

# END OF BUILD IMAGE


# This starts our application's run image - the final output of build.
FROM ubuntu:20.04

# INSTALL NODE
RUN apt-get update && apt-get install -y \
curl
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
RUN apt-get install nodejs -y

ENV NODE_ENV production

RUN addgroup -gid 1001 --system nodejs
RUN adduser --system nestjs -u 1001

# Pull the built files out of BUILD_IMAGE - we need:
# 1. the package.json and package-lock.json
# 2. the Nest build output
# 3. the node_modules.
WORKDIR /app
COPY --from=BUILD_IMAGE --chown=nestjs:nodejs /app/package.json /app/package-lock.json ./
COPY --from=BUILD_IMAGE --chown=nestjs:nodejs /app/node_modules ./node_modules
COPY --from=BUILD_IMAGE --chown=nestjs:nodejs /app/dist ./dist


RUN npx playwright install-deps 
RUN apt-get install xvfb 
RUN apt-get install x11-apps -y

RUN apt-get install screen -y
RUN screen -d -m Xvfb -ac :99 -screen 0 1280x1024x16
ENV DISPLAY :99

USER nestjs
WORKDIR /app
RUN npx playwright install

# Bind the server to 0.0.0.0:3000 on the assumption that
# firewalls in the VPC and container will prevent abuse of 0.0.0.0.
ENV PORT 3000
ENV HOST 0.0.0.0

EXPOSE 3000

CMD [ "npm", "run", "start:prod" ]

The problem: When invoking playwright via an http request, it output the error:

╔═════════════════════════════════════════════════════════════════════════════════════════════════╗
║ Looks like you launched a headed browser without having a XServer running.                      ║
║ Set either 'headless: false' or use 'xvfb-run <your-playwright-app>' before running Playwright. ║
║                                                                                                 ║
║ <3 Playwright Team                                                                              ║
╚═════════════════════════════════════════════════════════════════════════════════════════════════╝

From what I understand, the RUN screen -d -m Xvfb -ac :99 -screen 0 1280x1024x16 should have the XServer running. Checking via bash shows that $DISPLAY is :99. Why would playwright be unable to see the running XServer?

EDIT: This is the same result when invoking chrome from command line:

/home/nestjs/.cache/ms-playwright/chromium-1000/chrome-linux/chrome --no-sandbox
[419:419:0510/011729.759292:ERROR:ozone_platform_x11.cc(247)] Missing X server or $DISPLAY
[419:419:0510/011729.759331:ERROR:env.cc(225)] The platform failed to initialize.  Exiting.

0 Answers0