Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Run Karma in a container with Angular’s non-interactive command ng test --no-watch --no-progress --browsers=ChromeHeadless. The image must contain your locked Node dependencies and a discoverable Chrome or Chromium executable. Configure the launcher only as far as your repository requires, and treat flags such as --no-sandbox and --disable-dev-shm-usage as environment-specific trade-offs rather than default boilerplate.

Confirm that the workspace uses Karma

New Angular projects currently default to Vitest, while Karma remains supported. Before changing Docker or browser settings, inspect the repository’s Angular CLI version, angular.json, and test target. The current ng test command supports both Karma and Vitest runners.

Inspect the test target

cat angular.json
node --version
npx ng version

Look for a test target configured with Karma (the current Angular Karma guide uses a runner: "karma" option). Match the builder and option shape already present in your workspace; configurations from another Angular generation may not be interchangeable. In a multi-project workspace, identify the project name so the container can run only the intended target.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The CI command

Run this from the workspace root:

ng test --no-watch --no-progress --browsers=ChromeHeadless
  • --no-watch exits after the test run instead of waiting for file changes.
  • --no-progress keeps progress-bar output out of CI logs.
  • --browsers=ChromeHeadless selects Karma’s headless Chrome launcher.

For one project in a multi-project workspace, append its name, for example ng test web-app --no-watch --no-progress --browsers=ChromeHeadless. Use the exact project identifier from angular.json.

Choose how the container gets Chrome

Karma’s Chrome launcher can run Chrome or Chromium, including ChromeHeadless and ChromiumHeadless. Your image therefore needs a browser binary and a launcher that can discover it, or an explicit executable path.

System browser in the image

Installing the distribution’s Chrome or Chromium package keeps browser ownership visible in the Dockerfile. The package name and repository differ by base image, so pin the command to the Node/Linux combination your project already supports. Verify the resulting binary during the image build:

RUN command -v google-chrome || command -v chromium || command -v chromium-browser

This route can produce a smaller dependency graph than a second browser installer, but updates are tied to your operating-system package source.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Puppeteer-managed Chromium

Karma’s launcher documentation describes Puppeteer as one way to install Chromium for CI. It gives the project a browser-installation strategy that can be pinned alongside JavaScript dependencies, but downloads increase build time and image size. Keep the Puppeteer version and browser revision under the same lockfile policy as the application, and expose the installed executable to Karma if automatic discovery does not find it.

Neither approach is universally best. Decide using executable discovery, version pinning, update ownership, image size, build duration, and compatibility with the selected base image.

A version-aware Docker pattern

There is no single universal Dockerfile: Angular and Node compatibility, package manager, Linux distribution, and browser source all matter. The following pattern separates dependency installation, browser verification, and test execution. Replace the base image and browser-install step with versions approved by your repository.

FROM node:20-bookworm

WORKDIR /workspace

# Copy lockfiles first for repeatable, cacheable dependency installation.
COPY package.json package-lock.json ./
RUN npm ci

# Install Chrome or Chromium using the method selected for this image.
# Keep this step pinned to your distribution's documented package source.
# RUN apt-get update && apt-get install -y --no-install-recommends chromium

COPY . .

# Fail the build if no browser executable is present.
RUN command -v google-chrome || command -v chromium || command -v chromium-browser

CMD ["npx", "ng", "test", "--no-watch", "--no-progress", "--browsers=ChromeHeadless"]

If your project uses Yarn or pnpm, copy its lockfile and use the corresponding frozen-install command. Do not silently replace npm ci with a non-lockfile install in CI.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make Karma find the executable

First check the path inside the running image:

docker run --rm your-angular-test-image sh -lc 'command -v google-chrome || command -v chromium || command -v chromium-browser'

If the launcher cannot discover the binary, configure the path using the Karma launcher options already supported by your workspace, or set the browser environment variable expected by the launcher version you use. Keep that setting in source control so local and CI runs use the same definition. A custom launcher is appropriate when you need a controlled executable or additional flags; do not copy every flag from an example.

Sandbox and shared-memory settings

--no-sandbox

Chrome documentation describes --no-sandbox as sometimes used with headless mode but not recommended. Use it only when your container’s user or runtime setup genuinely requires it. If you must use it, isolate the CI job, avoid running untrusted workloads in the same container, and record the reason in the launcher configuration.

/dev/shm and --disable-dev-shm-usage

Chrome can crash or disconnect when the container’s shared-memory area is too small. Docker lets you increase it at runtime:

docker run --rm --shm-size=2g your-angular-test-image

Alternatively, Chrome’s --disable-dev-shm-usage flag makes the browser use another storage path. That can avoid a small shared-memory limit but may change I/O behavior. Inspect browser and container logs first, then adjust one relevant setting and retry; do not add both changes blindly.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Run locally and in CI

Build and execute

docker build -t angular-karma-ci .
docker run --rm --shm-size=2g angular-karma-ci

Use the same command in your CI job. Keep the workspace root as the working directory, preserve the lockfile, and publish the test exit code. A nonzero code should fail the pipeline.

Interactive diagnosis

When a run fails, open a shell in the image and check versions, paths, permissions, and memory limits:

docker run --rm -it --entrypoint sh angular-karma-ci
node --version
npx ng version
command -v google-chrome || command -v chromium || command -v chromium-browser
npx ng test --no-watch --no-progress --browsers=ChromeHeadless

For browser-level debugging, reproduce interactively where possible and retain Karma, Chrome, and container logs. Angular’s Karma guidance also recommends opening a test in the browser and using Chrome DevTools to inspect it and set breakpoints; a containerized reproduction may require forwarding a display or temporarily running an equivalent non-headless diagnostic environment.

Troubleshooting

“Chrome is not registered” or no browser launches

  • Cause: Chrome/Chromium is absent, not executable, or outside the launcher’s search path.
  • Fix: Run command -v inside the image, confirm file permissions, and configure the launcher with the discovered path. Ensure the selected browser name matches the launcher installed by your Karma packages.

The process waits forever

  • Cause: Watch mode is still enabled or the wrong project target was selected.
  • Fix: Use --no-watch, include --no-progress, and pass the project name when required.

Chrome starts and then disconnects

  • Cause: Resource pressure, especially a small /dev/shm, or an incompatible browser/runtime combination.
  • Fix: Inspect container limits and logs; retry with a larger --shm-size. If the evidence points to shared-memory exhaustion, test --disable-dev-shm-usage instead. Also verify that Node, Angular, Karma, and browser versions match the repository’s supported combination.

Tests fail only in the container

  • Cause: Missing system libraries, different timezone or locale, unavailable network resources, or environment-dependent application code.
  • Fix: Compare the container environment with local execution, log the browser’s stderr, and make required test data deterministic. Do not mask failures with broad flags such as --disable-web-security.

The image build is slow or unexpectedly large

  • Cause: Puppeteer downloading Chromium on every uncached build, or package layers invalidated by copying source before lockfiles.
  • Fix: Copy lockfiles and run the frozen install before application source, cache dependency layers in CI, and pin the browser-installation strategy.

Reliability and maintenance checklist

  • Record the Angular CLI, Node, Karma, launcher, and browser versions used by CI.
  • Use the repository’s lockfile and a repeatable browser source.
  • Verify the executable during image build rather than discovering its absence after deployment.
  • Allocate enough shared memory for the workload and monitor disconnect or crash logs.
  • Add only flags justified by an observed failure; avoid weakening browser security by habit.
  • Rebuild deliberately when browser security updates are needed, and review the resulting test logs.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is to capture a rendered page rather than run Angular unit tests, ScreenshotNeo provides a website screenshot API and MCP server. One request returns PNG, JPEG, WebP, or PDF, while its capture flow accepts consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a direct capture, see the ScreenshotNeo API documentation:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The same endpoint from Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

And Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Every plan includes the features; 1,000 screenshots per month are free without a card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Best Value
Docker Container Linux Devops Programming Coding T-Shirt
  • Docker, Docker Swarm, Docker Compose, Programmer, Developer, Coding, Programming, Software Engineer, Code, DevOps, Deploy, Deployment, Kubernetes, Salt, Puppet, Chef, Terraform, Container, AWS, Azure, Cloud, Geek, Funny, Computer, Software, Tech, IT
  • Integration, Scrum, Compile, Compilation, Science, Bug, Debug, Python, Linux, Java, Javascript, Scala, Dotnet, Kotlin
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

Frequently Asked Questions

Can I use Chromium instead of Google Chrome?

Yes. Karma supports Chromium launchers, including ChromiumHeadless. Install a Chromium executable and select the matching launcher name, or configure its path explicitly.

Should I always add –no-sandbox in Docker?

No. Chrome documentation says the option is not recommended. Add it only when your container security model requires it, and isolate that CI workload.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Which is better for CI: a system browser or Puppeteer Chromium?

Neither is universally superior. Compare executable discovery, version pinning, update ownership, image size, build time, and compatibility with your base image.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.