playwright
playwright copied to clipboard
[TIP] Run Playwright Tests on unsupported Linux distributions
To run Playwright on unsupported Linux distribution, you run run Playwright server in Docker while keeping your tests running on the host system:
Run Playwright Server in Docker
docker run -p 3000:3000 --rm --init -it mcr.microsoft.com/playwright:v1.41.0-jammy /bin/sh -c "cd /home/pwuser && npx -y [email protected] run-server --port 3000 --host 0.0.0.0"
It will output following when ready
Listening on ws://127.0.0.1:3000/
Point Playwright client to the server on Docker
If running @playwright/test, use environment variable, no other changes are needed.
PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:3000/ npx playwright test
Alternatively, for other applications and language ports, use browserType.connect API to use remote Playwright.
const browser = await playwright['chromium'].connect('ws://127.0.0.1:3000/');
Network
Make sure that the host network is available in your Docker container if you are testing local servers:
docker run --add-host=hostmachine:host-gateway
This will make hostmachine
point to the host's localhost. Note that all the tests would also need to use hostmachine
in the URLs to access servers on the host. Alternatively, you can follow unconventional route and do docker run --add-host=localhost:host-gateway
at your own risk.
Really cool. Should sandboxing work in the container?
@aslushnikov thanks for pointing this our over on https://github.com/microsoft/playwright/issues/9199
This is great, exactly what we needed, but the first thing that happens when you start the playwright server is that it goes out to npmjs to install the playwright-core
dependency. Which doesn't work in say a CI/CD env with no outbound internet access.
Ideally, the container should be self-contained. Why not install that dependency when creating the container so that it is fully self-contained and works in an offline environment?
There are always difficulties with network_mode: host
that only works on Linux distros. Alternatively you can use --add-host=hostmachine:host-gateway
, but could also lead to issues.
You can apply a small hack which allows playwright to listen 0.0.0.0. Since by default playwright server is not capable for that
: yarn playwright run-server --help
yarn run v1.22.19
$ node_modules/.bin/playwright run-server --help
Usage: yarn playwright run-server [options]
Options:
--port <port> Server port
--path <path> Endpoint Path (default: "/")
--max-clients <maxClients> Maximum clients
--mode <mode> Server mode, either "default" or "extension"
-h, --help display help for command
You can manually patch
node_modules/playwright-core/lib/remote/playwrightServer.js
Replacing
- server.listen(port, () => {
+ server.listen(port, '0.0.0.0', () => {
And run docker with docker run -p 3000:3000
If you need to automate that you can use patch-package
Also note, that when you run playwright from docker it has to have access to your webserver. Which means you need to run it inside same docker container as playwright. Otherwise you're stuck to an option that PO described with --add-host=hostmachine:host-gateway
Unfortunately, the container doesn't work at all for me.
I have a fresh setup of Playwright with npm init playwright@latest
and followed the instructions above. The container starts fine (Listening on ws://127.0.0.1:3000/
) but the tests are just stuck.
> PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:3000/ npx playwright test
Running 6 tests using 6 workers
[6/6] [chromium] › example.spec.ts:10:5 › get started link
When running npx playwright test
by itself, the command finishes almost immediately and has 4 of 6 passing tests (webkit failing due to missing dependencies).
6.5.9-arch2-1 Linux
Hello, I have an odd issue. I tried using the docker image inside Rocky Linux and it worked perfectly, webkit passed no problem. What I noticed is that if after running it on a specific port, if I reboot the server, it will no longer work on the same port. I actually have to change the port to get it to work again. If I reboot again, now the new port I used won't work, but if I switch back to the original port, now that will work again. The error I get is as follows:
Error: browserType.connect: WebSocket error: connect EHOSTUNREACH 127.0.0.1:10700 =========================== logs =========================== <ws connecting> ws://127.0.0.1:10700/ <ws error> ws://127.0.0.1:10700/ error connect EHOSTUNREACH 127.0.0.1:10700 <ws connect error> ws://127.0.0.1:10700/ connect EHOSTUNREACH 127.0.0.1:10700 <ws disconnected> ws://127.0.0.1:10700/ code=1006 reason= ============================================================
The command I use is :
docker run -p 10700:10700 --rm --init -it mcr.microsoft.com/playwright:v1.39.0-jammy /bin/sh -c "cd /home/pwuser && npx -y [email protected] run-server --port 10700"
So, every time I reboot, I have to keep switching back and forth between two ports 10700 and 10600. Do you have any idea why this would be happening?
Even if I re-download the docker image it still will not work using the previous port used prior to reboot.
Seems like some sort of cache issue.
Any help is appreciated.
I have CentOS 7, which is definitely unsupported.
Then I found this issue which described how we can use playwright-java as the client and playwright docker as the server which should work on unsupported OS.
So I tried it using PW 1.40. I found that before you can call browserType.connect per the instructions in this issue, you need a Playwright instance. To get that, you can Playwright.create(), but this creates a temporary node instance using /tmp and that doesn't work on unsupported OS.
/tmp/playwright-java-7742446124117836956/node: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by /tmp/playwright-java-7742446124117836956/node)
So seems the instructions in this issue are incorrect (or at least incomplete) for Java. It can be made to work, but not with the instructions as given.
After bit more searching I found https://github.com/microsoft/playwright-java/issues/1016 and was able to use it to use my own host node rather than the PW supplied one which does not work. I installed node manually on CentOS and then set system property "playwright.nodejs.path" to point to it, and it seemed the local node could be started.
After that I set env PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=true to prevent PW trying to download and install browsers on the host (that I didn't need and won't work on the unsupported OS).
It would be much cleaner and simpler if the playwright-java API could be extended to allow connection to a previously started driver in Linux, avoiding Playwright.create() and local node altogether, similar to Selenium RemoteWebDriver.
Anyway. here is the working test case. I think it should be adaptable to any OS which can run Java and Node.
@Test
public void testSomething() {
// Playwright will try and download and install node AND browsers automagically.
// These do not work on CentOS7, as not supported O/S. So, we need another approach.
// Playwright provide a docker container with correct node and browsers inside.
// However, playwright-java requires a host node purely to "bounce" to the docker node.
// So we have to install host node, point PW at it, and tell PW not to download browsers too.
// Install node on the host, e.g. in CentOS
// sudo yum install nodejs
// Find the install location of host node and use it to set the following variable
// which node
String hostNodePath = "/usr/bin/node";
// Start PW docker as per https://github.com/microsoft/playwright/issues/26482
// Tell PW to use our host node for the "bounce" to Docker node
System.setProperty("playwright.nodejs.path", hostNodePath);
// Tell PW not to install host browsers, as we'll be using browsers from Docker container
Map<String, String> env = new HashMap<String, String>() {{
put("PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD", "true");
}};
Playwright.CreateOptions options = new Playwright.CreateOptions().setEnv(env);
try (Playwright playwright = Playwright.create(options)) {
// Connect to the node (driver) inside of docker
Browser browser = playwright.chromium().connect("ws://127.0.0.1:3000/");
// Test as usual
Page page = browser.newPage();
page.navigate("http://playwright.dev");
System.out.println(page.title());
}
}
My usage would be much easier if I can avoid installing native software on the host. So I might raise an issue on playwright-java to see if they can help with a pure Java client API.
https://github.com/microsoft/playwright-java/issues/1446
I have the same issue as https://github.com/microsoft/playwright/issues/26482#issuecomment-1796970328. Tests are stuck. I'm specifying the service inside a docker-compose
file, as I also need other containers running. I'm using port 5000 and specifying localhost
in the extra_hosts
property of the service. I hope everything is setup correctly - if not, I'd be happy to hear a suggestion (I'm not entirely sure if I'm using the extra_host
option appropriately):
playwright:
image: mcr.microsoft.com/playwright:v1.37.0-jammy
restart: always
ports:
- '5000:5000'
container_name: "playwright-e2e"
command:
[
"/bin/sh",
-c,
"cd /home/pwuser && npx -y [email protected] run-server --port 5000"
]
extra_hosts:
- "localhost:host-gateway"
I run PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:5000/ npx playwright test
. The test setup starts fine (database seed), but then the tests hang indefinitely on all browsers. UI mode opens, but when I run an individual test, it hangs on browserType.connect
.
If I use the hostmachine
for the extra_host
option, the situation is worse, since then the database seeding doesn't work at all. Tests don't use localhost in their URL's since they are always poinitng to specific endpoints ("/", etc.).
~Shutting down the docker containers also takes 10 seconds due to the playwright service taking a long time to exit.~ Resolved by specifying the init: true
in the docker compose file.
I'm using Fedora 39, but this shouldn't really be a factor here. A workaround to install needed system dependencies for the distro would be very welcome, even though having a Docker image available is a great feature.
Also, if the Docker image documentation will be expanded, I would suggest also including a docker-compose scenario, as this is probably a common use-case.
EDIT:
The 1.40 version of the image does not hang, but the connection is refused if I use the extra_hosts
with the gateway mapping. Currently, I found two options to make it work:
- Use the
network_mode: host
option and remove the port mappings. This allows the use oflocalhost
directly. The host network mode only works on Linux hosts. - If you run your web server in a way that exposes the ports (for example
vite preview --host
, then you can connect to the port either via the host's IP address (192...
), or the docker interface address (172...
)
--add-host=hostmachine:host-gateway
It works, but can you please update it to 1.41 and add --add-host=hostmachine:host-gateway
by default?
-
docker run --add-host=hostmachine:host-gateway -p 3000:3000 --rm --init -it mcr.microsoft.com/playwright:v1.41.0-jammy /bin/sh -c "cd /home/pwuser && npx -y [email protected] run-server --port 3000"
-
PW_TEST_CONNECT_WS_ENDPOINT=ws://localhost:3000/ npx playwright test
This only runs the Playwright Webserver in a dockerized environment, but the actual test execution, and therefore, the browser dependencies, still runs in the host, correct?
To run Playwright with dockerized browsers, one could run this inside their PW tests directory:
docker run \
--add-host=hostmachine:host-gateway \
--rm \
--init \
-it \
-v $(pwd):/home/pwuser/tests \
mcr.microsoft.com/playwright:v1.41.0-jammy \
/bin/sh -c "cd /home/pwuser && npm install @playwright/[email protected] && npx playwright install && npx playwright test"
Only caveat with dockerized browser approach is that you can only run it headless. You loose out on many cool Playwright features such as --headed
, or --ui
.
Ideally, Playwright should be able to install the browsers and dependencies in Linux to run the test natively so that we can have headed runs.
Hi @pavelfeldman ,
do you per chance know whether PW_TEST_CONNECT_WS_ENDPOINT
is also supported in the Java client?
I'm seeing my test fail in Jenkins CI in a way that lets me doubt this is supported in Java. Also https://github.com/search?q=repo%3Amicrosoft%2Fplaywright-java%20PW_TEST_CONNECT_WS_ENDPOINT&type=code yields no results, while the same search in https://github.com/microsoft/playwright has a good number of code results...
Answer to self: in the Java client API this works differently, and without the environment variable, as shown here: https://github.com/RG9/remote-playwright-demo/blob/main/src/main/java/org/example/App.java#L18
@jfrantzius for Java you can just use BrowserType.connect().
The link above shows connectOverCDP which is about CDP and Chrome only while this issue is about connect() which supports all the browser types Playwright supports.
Thx @mxschmitt !
For everyone else using this script, I had problems with WebSocket errors, had to add a few lines to wait for the server to be ready in the Docker script before finishing:
#! /bin/bash
if ! curl --output /dev/null --silent --head --fail http://localhost:9009/status
then
echo "Starting PlayWright Server"
docker run \
-d -p 9009:9009 \
--add-host=hostmachine:host-gateway \
--rm --init -it \
mcr.microsoft.com/playwright:v1.41.1-jammy \
/bin/bash -c "cd /home/pwuser && npx -y [email protected] run-server --port 9009"
# Wait for server to start
while ! curl --output /dev/null --silent --head --fail http://localhost:9009/status; do
sleep 0.2
done
fi
@Luc45
You loose out on many cool Playwright features such as --headed, or --ui.
If you run Playwright with --ui-host=0.0.0.0
as described here, you can simply access the Playwright UI in a regular browser running on your host.
If you run Playwright with --ui-host=0.0.0.0 as described here, you can simply access the Playwright UI in a regular browser running on your host.
You're right, this is awesome and addresses my concern with Dockerized runs.
The only thing I'm still trying to do is npx playwright codegen
in a dockerized run, as it doesn't seem to have --ui-host
parameter like npx playwright test
does.
Trying to piece together a working solution together from the posts here (I am running on Alma).
the original post - it is not correct, is it? it states to set host to 0.0.0.0 and then says it will respond with listening on 127.0.0.1, which of course it does not say, it says listening on 0.0.0.0. And then it runs: "PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:3000/ npx playwright test" which seems wrong as well, as it is not listening on 127.0.0.1
regardless, if i do what is posted or "fix it" to run on 0.0.0.0, same result. it just hangs and no report is created.
The same happens for the solution posted by Luc45 on Jan 19 (why hasn't github figured out numbering comments??). It just hangs, nothing created.
If i dont run docker and just run: npx playwright test, i get output saying all tests failed and a playwright-reports/index.html with a nicely formatted report; saying all tests failed. which would seem to indicate pw runs on alma, but possibly the tests are not configured correctly?
Trying to piece together a working solution together from the posts here (I am running on Alma).
the original post - it is not correct, is it? it states to set host to 0.0.0.0 and then says it will respond with listening on 127.0.0.1, which of course it does not say, it says listening on 0.0.0.0. And then it runs: "PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:3000/ npx playwright test" which seems wrong as well, as it is not listening on 127.0.0.1
regardless, if i do what is posted or "fix it" to run on 0.0.0.0, same result. it just hangs and no report is created.
The same happens for the solution posted by Luc45 on Jan 19 (why hasn't github figured out numbering comments??). It just hangs, nothing created.
If i dont run docker and just run: npx playwright test, i get output saying all tests failed and a playwright-reports/index.html with a nicely formatted report; saying all tests failed. which would seem to indicate pw runs on alma, but possibly the tests are not configured correctly?
Playwright will run, but I think the system dependencies that are needed and the browsers won't be installed which is also why tests are probably failing?
For me, the following compose configuration works (similar to configuration from my post on 31 Dec 2023)
SERVICE_NAME:
image: mcr.microsoft.com/playwright:v1.40.0-jammy
restart: always
container_name: "CONTAINER_NAME"
init: true
ipc: host
command:
[
"/bin/sh",
-c,
"cd /home/pwuser && npx -y [email protected] run-server --port PORT_NUMBER"
]
network_mode: host
Then you can run it with PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:PORT_NUMBER/ npx playwright
test`
Thanks for the quick reply. From what you wrote i put together the newbie version:
- install docker-compose
- create a docker-compose.yml with the following:
services:
playwright:
image: mcr.microsoft.com/playwright:v1.40.0-jammy
restart: always
container_name: "playwright"
init: true
ipc: host
command:
[
"/bin/sh",
-c,
"cd /home/pwuser && npx -y [email protected] run-server --port 3000"
]
network_mode: host
- run docker-composer up
- PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:3000/ npx playwright test
after all that, same result as before. this outputs nothing.
The docker compose up command seems to be working correctly as it outputs the "Listening on..." message. However, are you inputting the command directly in the same terminal as the one that you've ran the docker compose command on?
If that is so, the command will not work, as the docker process is running in the foreground and you do not have access to the shell as such. Either try running the command in a separate terminal or run the docker compose command with the -d
flag so that the docker compose will run in detached mode and release the shell back to you.
If that still does not work, you can try running the Playwrighht in UI mode
"PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:5000/ npx playwright test --ui-port=SOME_OTHER_PORT
Then open the browser at localhost:SOME_OTHER_PORT and see if the Playwright's UI is showing and if it recognizes your tests.
Then open your browser at localhost:SOME_OTHER_PORT
woke up this morning and that dawned on me... this is run as a service and i need to execute npx in a different window. duh. Tried that and then could see a client/server pw version mismatch; not sure why but changed the version in docker.compose.. and it is working now.
thanks for getting back to me.
hey theere i am still facing an issue while running a test
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:5173/
Call log:
- navigating to "http://localhost:5173/", waiting until "load"
my vite app is running at 5173 , how can i solve this , the app is running locally fine How can i fix this issue
@Kinfe123 try to use network:host on your docker command (look it up for exact syntax)
Hello!
I’m currently trying to make Playwright work in Docker so I can test on unsupported browsers. I’ve been reading this page for hours, trying multiple things. I’m not proficient with Docker.
My application runs on http://localhost:3000 and works fine on my browser
Here are the conf I’m using, and the output / issue
The docker-compose.yml
services:
playwright:
image: mcr.microsoft.com/playwright:v1.41.0-jammy
restart: always
container_name: "playwright"
init: true
ipc: host
ports:
- '5000:5000'
command:
[
"/bin/sh",
-c,
"cd /home/pwuser && npx -y [email protected] run-server --port 5000"
]
# network_mode: host
extra_hosts:
- "localhost:host-gateway"
The command I run :
PW_TEST_CONNECT_WS_ENDPOINT=ws://localhost:5000/ npx playwright test
The output I got :
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://127.0.0.1:3000/auth/signin Call log: - navigating to "http://127.0.0.1:3000/auth/signin", waiting until "load"
I can go on localhost:5000, it says "running"
If I remove the commentary and set the network_mode to host, I got the following output:
Error: browserType.connect: WebSocket error: connect ECONNREFUSED ::1:5000
localhost:5000 does not reply in this configuration
Maybe @Kinfe123 or @Luc45 have an idea, as it seems to be the same issue from the last posts?
If you set network_mode to host, do you also comment out the extra_hosts line?
In my case, I only have the network_mode se tot host and no extra hosts specified. I have the base url specified in the Playwright config.
Also, try using a newer image, like mcr.microsoft.com/playwright:v1.43.0-jammy (I'm not sure why the Docker hub entry still specifies the 1.40 version). In that case you should also update the playwright dependency in your package.json
Thank @jericirenej, I updated the image, but I still have the WebSocket Error
Error: browserType.connect: WebSocket error: connect ECONNREFUSED ::1:5000
My docker-compose :
services:
playwright:
image: mcr.microsoft.com/playwright:v1.43.0-jammy
restart: always
container_name: "playwright"
init: true
ipc: host
ports:
- '5000:5000'
command:
[
"/bin/sh",
-c,
"cd /home/pwuser && npx -y [email protected] run-server --port 5000"
]
network_mode: host
# extra_hosts:
# - "localhost:host-gateway"
My playwright-config.ts
import { defineConfig, devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://127.0.0.1:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
// {
// name: 'firefox',
// use: { ...devices['Desktop Firefox'] },
// },
// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],
/* Run your local dev server before starting the tests */
webServer: {
command: 'yarn dev',
url: 'http://127.0.0.1:3000',
reuseExistingServer: !process.env.CI,
},
});
I have commented next to every browser so I could write tests and it works outside of Docker (but I can’t test Safari or Edge)
The command i use
PW_TEST_CONNECT_WS_ENDPOINT=ws://localhost:5000/ npx playwright test
What if you replace the 127.0.0.1
in your playwright.config
with localhost
?
On my machine, if I use the exact IP address, the tests hangs and I get a config.webServer
timeout, but with localhost
it runs.
Update:
For my run command, I have "PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:5000/ npx playwright test"
in my package.json
. However, using this or the localhost makes no difference on my end, the test runs with my current settings (localhost in playwright config). I do not get the web socket timeout.
Also, try removing the port mappings, if you use the host network mode. Do note, that the host networking mode is only available on Linux OS (see my previous post)