skip to content

Container Images and CI

The official container image and the CI wiring round it: matching browser builds to the library version, installing system dependencies, and getting the report out of the job.

on this pageshow

explore

questions

5

In Playwright, what does `npx playwright install --with-deps` do that plain `npx playwright install` does not?

level: juniorimportance: must knowfreq 70%

answer

  1. Two installs hide behind one flag
  2. Binaries alone are not enough
  3. Dynamic linking needs system libraries
  4. Needs root and a supported distro
  5. Unnecessary inside the official image

basics

~20 s

It also installs the operating-system packages the browsers link against, using the system package manager, before downloading them. Plain install only downloads the browser binaries, which then fail to launch on a bare Linux runner.

solid answer

~40 s

`npx playwright install` downloads the browser builds pinned to your installed Playwright version into its browser cache. That is only half the job on Linux: those binaries are dynamically linked and need graphics, font and audio libraries that a bare CI runner or slim base image usually lacks. `--with-deps` adds that half, shelling out to the system package manager first — so it needs root or `sudo`, and targets Debian/Ubuntu-family images. `npx playwright install-deps` is the same OS-package step on its own. Both forms take browser names, so `npx playwright install --with-deps chromium` skips two engines you never launch. Inside `mcr.microsoft.com/playwright` you need neither: the browsers and libraries are already baked into the image.

code

bash · 3 lines
bash
npm ci
npx playwright install --with-deps chromium
npx playwright test

go deeper

for a junior

Remember the split: plain install downloads browsers, and the flag adds the Linux system packages they need to start. On a bare CI runner you want the flag.

for a middle

Explain why the second half exists: the browser binaries are dynamically linked, so missing shared libraries kill them at launch even though the download succeeded.

for a senior

Show the operational angle: it needs root and distro mirrors, it runs on every job unless baked into an image, and naming a single browser cuts cold setup materially.

for a principal

Decide the policy — install per job, cache the browsers, or bake an image — and make sure whichever route you pick installs the version the lockfile just resolved.

## One command, two different installs `npx playwright install` downloads **browser builds** — the Chromium, Firefox and WebKit binaries pinned to your installed `@playwright/test` version — into Playwright's browser cache. That is a plain file download; it needs network access and disk, nothing more. Those binaries then have to *link*. On Linux a browser is a dynamically linked executable that needs graphics, font, audio and X/GTK libraries present on the host. A stock CI runner or a slim base image usually has few of them. `npx playwright install --with-deps` adds that second install: it runs the system package manager to put those shared libraries in place, then downloads the browsers. `npx playwright install-deps` is the same OS-package half on its own, for when the browsers are already present but the libraries are not. ## What the deps half needs - **Elevated privileges.** It shells out to the system package manager, so it needs root or `sudo`; an unprivileged CI user gets a permission failure, not a silent skip. - **A supported distro.** The dependency lists Playwright ships target Debian/Ubuntu-family images. On anything else you install the libraries yourself. - **Network to the distro mirrors**, not just to the browser CDN — two different egress paths, which matters on a locked-down runner. - **Time on every run** unless you bake it into an image, because packages installed into a throwaway runner die with the runner. ## Failure modes it prevents Without the OS packages, `npx playwright install` looks like it worked and the failure arrives later, at launch, as a browser process that exits immediately or a message naming a missing `.so` file. That is the confusing shape: the download step is green, the test step dies. `--with-deps` collapses both halves into one step that fails loudly at setup time. | Situation | What to run | Why | |---|---|---| | Bare Ubuntu CI runner, root available | `npx playwright install --with-deps` | Neither browsers nor libraries are present | | Inside `mcr.microsoft.com/playwright:v1.63.0-noble` | nothing | Browsers and libraries already ship in the image | | Slim custom image, browsers cached in a volume | `npx playwright install-deps` | Only the OS libraries are missing | | Local developer laptop | `npx playwright install` | The desktop OS already has the libraries | ## Narrowing what you download Both forms take browser names, so a payroll regression suite that only ever runs Chromium can do `npx playwright install --with-deps chromium` and skip two engines' worth of download and disk. That is usually the single biggest cut to a cold CI setup step. Add engines back when a project in the config actually needs them — installing less than the config launches just moves the failure to launch time. ## Where it fits in a job 1. Check out the repository and install npm dependencies as usual; this step does **not** fetch browsers for you. 2. Run `npx playwright install --with-deps` (optionally naming browsers) as an explicit step. 3. Run the suite. Inside the official image, step 2 disappears, which is most of the reason to use the image at all. Running `--with-deps` there anyway is harmless but wasteful: it re-checks packages that were baked in at build time, adding a slow apt round-trip to every job for no change in outcome. One last point worth saying out loud in an interview: the flag installs **operating-system** dependencies, not npm ones. It has nothing to do with `package.json`, lockfiles, or which browsers your config declares — it is the bridge between a downloaded binary and a Linux box that can actually execute it.

  • What breaks if you run plain install on a bare Ubuntu runner?
    The download step goes green and the failure moves to launch time: the browser process exits immediately, typically naming a missing shared library. That split is what makes it confusing — the setup step reports success while the test step dies, so people look at the tests rather than at the runner's packages.
  • Why might --with-deps fail on a CI runner that has network access?
    It runs the system package manager, so it needs elevated privileges and reachable distro mirrors — a different egress path from the browser CDN. An unprivileged user gets a permission error, and a locked-down runner can reach the browser downloads while the package repositories are blocked.

saying these in an interview costs you the question

  • Thinks it installs npm dependencies
  • Believes installing the package downloads browsers automatically
  • Runs it inside the official image out of habit
  • Expects it to work without root privileges
  • Assumes it works on any Linux distribution
open as a page

Why must the mcr.microsoft.com/playwright image tag match your installed Playwright version?

level: middleimportance: must knowfreq 62%

basics

~20 s

Each Playwright release pins exact browser builds, and the image ships only those. A mismatched tag leaves the library looking for a browser revision that is not in /ms-playwright, so every test fails at launch.

open as a page

What does Playwright change about a run when the CI environment variable is set?

level: middleimportance: should knowfreq 44%

basics

~20 s

Only the default reporter: with CI set and no reporter configured, Playwright prints one character per test instead of the interactive line-per-test output. Everything else people attribute to it is written in the project's own config.

open as a page

Playwright's Chromium crashes pages only when the suite runs inside a container — what does `--ipc=host` change?

level: seniorimportance: should knowfreq 48%

basics

~10 s

Containers get a private, small /dev/shm, and Chromium passes large buffers through that shared memory. When it fills, renderers die and pages crash. Running with --ipc=host gives the container the host's shared memory instead.

open as a page

How would you decide between the official Playwright image and `playwright install --with-deps` on a CI runner?

level: principalimportance: should knowfreq 36%

basics

~20 s

Choose the image when the environment should be pinned and the job needs nothing else; choose your own base plus an install step when it needs other tooling. Often the answer is an image built from the official one.

open as a page