← Back to blog

Playwright in Docker: The Browser Path Gotcha That'll Waste Your Afternoon

You build your screenshot service. It works perfectly on your machine. You deploy it to Docker and get:

browserType.launch: Executable doesn't exist at
/home/rails/.cache/ms-playwright/chromium_headless_shell-1208/...

Classic.

The Problem

Playwright installs browser binaries to a user-specific cache directory. By default, that's ~/.cache/ms-playwright/ on Linux.

In Docker, you typically:

  1. Install Playwright as root during the build
  2. Run the app as a non-root user (like rails, node, or appuser)

The browsers get installed to /root/.cache/ms-playwright/, but your app looks in /home/youruser/.cache/ms-playwright/. Empty directory. Crash.

The Fix

Set PLAYWRIGHT_BROWSERS_PATH to a shared location:

ENV PLAYWRIGHT_BROWSERS_PATH="/opt/playwright-browsers"

RUN npm install -g playwright@latest && \
    npx playwright install --with-deps chromium && \
    chmod -R o+rx /opt/playwright-browsers

The key pieces:

  • PLAYWRIGHT_BROWSERS_PATH — tells Playwright where to install AND where to look
  • chmod -R o+rx — makes the directory readable by all users
  • Set the ENV before the install so it takes effect

Why --with-deps Matters

On Debian/Ubuntu-based images, Chromium needs system libraries. --with-deps installs them automatically — about 20 libraries including libnss3, libatk, libgbm, and more. Without it, you'll get a different error about missing shared libraries.

Quick Sanity Check

SSH into your container and verify:

echo $PLAYWRIGHT_BROWSERS_PATH
ls -la /opt/playwright-browsers/
su - appuser -c "npx playwright install --dry-run"

Performance Tip

First render after a cold container start will be slow (~2-5s) because Chromium needs to spin up. Subsequent renders reuse the warm process. If you need consistent sub-second times, keep a warm browser instance pool.

I hit this exact bug building Rendly. Wasted 30 minutes before the obvious hit me. Now you don't have to.

Ready to get started?

Try Rendly free — 100 renders/month, no credit card required.

Sign up for free →