Why Chrome crashes in Docker
Headless Chrome dies inside a container with an error that tells you nothing. The cause is a single default nobody thinks to check.
Your renderer works on the host. Inside a container it dies partway through, usually with something as unhelpful as Target closed or Protocol error. The logs point nowhere useful.
Sixty-four megabytes
Docker gives every container a /dev/shm of 64MB. Chrome uses shared memory heavily for its renderer processes, and 64MB runs out fast — faster the more tabs or frames you render in parallel.
Check what your container actually has:
docker run --rm my-renderer df -h /dev/shm
# Filesystem Size Used Avail Use% Mounted on
# shm 64M 0 64M 0% /dev/shm
Now compare it to the host, which typically has half of RAM available. The gap is the bug.
The fix
services:
renderer:
build: .
shm_size: '2gb'
Or on the command line:
docker run --shm-size=2g my-renderer
Two gigabytes is comfortable for most rendering work. If you run several jobs concurrently in one container, scale it up rather than guessing.
The flag you will be told to use instead
Every thread on this suggests --disable-dev-shm-usage, which makes Chrome write to /tmp instead of shared memory.
const browser = await puppeteer.launch({
args: ['--disable-dev-shm-usage'], // works, but slower
});
It does work. It also moves that traffic from memory to disk, which costs you throughput on exactly the workload you containerised for speed. Use it when you cannot control the runtime; set shm_size when you can.
While you are in there
Two more that bite in the same place:
# Chrome needs system libraries a slim image does not carry
RUN apt-get update && apt-get install -y --no-install-recommends \
libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 \
libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 \
libxfixes3 libxrandr2 libgbm1 libpango-1.0-0 libasound2 \
&& rm -rf /var/lib/apt/lists/*
And do not reach for --no-sandbox as a first move. It silences a class of permission errors by removing a security boundary, on a process that renders content you may not control. Run the container as a non-root user and keep the sandbox.
The general shape
The symptom appeared in Chrome. The cause was a container default that has nothing to do with Chrome. When something works on the host and fails in a container, compare the two environments directly — df, ulimit, nproc, fc-list — before you debug the application at all.