BROWSER

Running it

Running in Docker

The published Browser image, the four docker run flags that matter, and why running as root breaks Chromium.

Browser needs a browser, and a browser needs a long list of system libraries that differ between distributions. On a laptop rfbrowser init handles it. On a CI runner, a colleague's machine, or a distribution nobody tested, it is the part that goes wrong.

The published image removes that problem: Python, Node, Robot Framework, Browser and the browser binaries that ship in Playwright's base image, in versions known to work together.

Pull it

The same image is published to two registries. Pick whichever your infrastructure already authenticates against — the same recipe, built from one Dockerfile in the same release job.

docker pull marketsquare/robotframework-browser:20.3.0docker pull ghcr.io/marketsquare/robotframework-browser/rfbrowser-stable:20.3.0
TagPoints at

Both linux/amd64 and linux/arm64/v8 are built, so it runs natively on an Apple Silicon machine as well as on an x86 runner.

Run your suite

docker run --rm \  -v "$(pwd)/tests:/test" \  --ipc=host \  --user pwuser \  --security-opt seccomp=seccomp_profile.json \  marketsquare/robotframework-browser:20.3.0 \  bash -c "robot --outputdir /test/output /test"

Your suite is mounted in rather than copied, and the output directory is inside that same mount — which is what gets log.html back onto your machine after the container exits. A container writing its report to its own filesystem and then being removed is the classic first mistake.

The container writes as pwuser, not as your user, so the mounted directory has to be writable by that account. If it is not, the run dies trying to create output/. Create it up front and open it up — this project's own CI does mkdir output && chmod -R 777 output — or skip the mount and docker cp the results out afterwards.

The flags, and why each one is there

None of these are ceremony. Each fixes a specific, confusing failure.

--user pwuser

Insurance, not a requirement. The image already ends on USER pwuser, so it runs as that user by default and this flag changes nothing — keep it only if your platform is liable to force root. What matters is not overriding it with --user root: everything is installed for pwuser, from the virtualenv at /home/pwuser/.venv to the caches and file permissions, and running as root causes failures that look like browser crashes.

--ipc=host

--ipc=host is what this project recommends for Chromium, and it is what its own container tests use. The reason comes from Playwright's Docker guide rather than from Browser: Chromium allocates shared memory through /dev/shm, Docker's default is 64 MB, which a real page will exhaust — and Chromium's response to running out is to crash a renderer, mid-test, non-deterministically. It presents as flakiness, and you will look for it in your test before you look for it in your container runtime.

--ipc=host gives the container the host's IPC namespace and the problem disappears. If your platform will not allow it, --shm-size=2gb is the second-best answer.

--security-opt seccomp=seccomp_profile.json

Chromium's sandbox needs syscalls that Docker's default seccomp profile blocks. Playwright publishes a profile that permits exactly those:

wget https://raw.githubusercontent.com/microsoft/playwright/master/utils/docker/seccomp_profile.json

The alternative you will find on the internet is --cap-add=SYS_ADMIN or --no-sandbox. Both work by turning the sandbox off. The seccomp profile keeps it on, which for a container that loads arbitrary web pages is the difference that matters.

--rm

Housekeeping. Test containers are disposable, and without it a CI runner accumulates them until the disk fills.

Headless and headful

The image is built on Microsoft's Playwright image, which includes the dependencies for headful runs as well as headless. New Browser is headless by default and that is what you want in CI — note that Open Browser defaults the other way.

Headful needs a display, and the image already carries Xvfb: prefix the command with xvfb-run, which is exactly what this project's own headful container tests do. A VNC sidecar is only needed if you want to watch the run.

What is actually in the image

Worth knowing, because it explains the constraints in Building your own image:

LayerWhat it provides

That last row is the non-obvious one. The browsers in this image come from the Playwright base image, not from rfbrowser init. It is why the image is far smaller than an install that downloads its own browser binaries on top of the base image's — and also why the base image's Playwright can differ from the one Browser was built against, since nothing in the image re-downloads browsers to match.

Checking what you got

docker run --rm marketsquare/robotframework-browser:20.3.0 rfbrowser --version

Prints the Browser library version, the Robot Framework version and the Playwright version in one go. When something behaves differently in the container than on your machine, run it in both places first — the answer is usually in the diff.

Next

  • Adding your own dependencies, and pinning safely: Building your own image.
  • If you run suites in parallel, read The Node process first: each Robot Framework process starts its own Node process, inside a container as much as outside it.