Running Stably-powered Playwright tests inside Docker gives you a clean, repeatable environment that behaves the same on your laptop, in CI, or on self-hosted runners. The workflow mirrors the local test flow and the GitHub Actions setup—use the same npx stably test
command, but package it alongside the services your application needs (front end, APIs, databases, queues, and more).
Prerequisites
- Docker (or another OCI-compatible runtime) installed
- Node.js 18+ available in your base image
- A Playwright project initialized in your repository
- Stably installed as a project dependency (
npm install --save-dev stably
)
Quick Setup
1. Extend your existing application image with Playwright dependencies
Add the Playwright browsers and keep your build steps for the app under test. The example below installs dependencies, builds a front end, and leaves the app ready to run inside the container:
FROM node:18-bullseye-slim AS tester
WORKDIR /app
# Install dependencies first for better layer caching
COPY package*.json ./
RUN npm ci
# Copy source code (front end, tests, utilities, etc.)
COPY . .
# Build or seed any assets your app needs before tests execute
RUN npm run build
# Ensure Playwright browsers are available inside the container
RUN npx playwright install --with-deps
# Default command mirrors running tests locally
CMD ["npx", "stably", "test"]
If you already build separate images for your front end, back end, or supporting services, keep those Dockerfiles untouched and introduce a dedicated test image (like the tester
stage above) that shares the same source tree.
2. Build the image or test stage
docker build -t stably-tests .
3. Run tests alongside your stack
Start the supporting containers (API, database, etc.), then run the test image with the same environment you would use locally:
docker run --rm \
--network my-app-network \
-e STABLY_API_KEY=$STABLY_API_KEY \
-e BASE_URL=http://web:3000 \
stably-tests
Using a shared Docker network allows the test container to reach the services it is validating. The example sets BASE_URL
to the DNS name of a front-end container (web
), but you can add any env vars, secrets, or config files your tests rely on.
Store your Stably API key securely—use environment files, Docker secrets, or your orchestrator’s secret manager instead of hardcoding it in the image.
Coordinate with Other Services
- Compose or orchestration tools: Launch your services with Docker Compose, Kubernetes, or your preferred orchestrator. Attach the Stably test container to the same network so it can call real APIs and front ends.
- Wait for readiness: Use health checks,
dockerize
, wait-for-it
, or your own scripts to ensure dependent services are ready before tests run.
- Seed data: Run migrations or seed scripts in the same compose file so the environment mirrors production as closely as necessary.
services:
web:
build: ./frontend
environment:
API_URL: http://api:4000
api:
build: ./api
depends_on:
db:
condition: service_healthy
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 10
tests:
build:
context: .
target: tester
depends_on:
- web
- api
environment:
STABLY_API_KEY: ${STABLY_API_KEY}
BASE_URL: http://web:3000
command: ["npx", "stably", "test"]
Run everything together and exit with the test result:
docker compose up --build --exit-code-from tests
Customize Playwright and Stably Flags
Pass any additional CLI flags exactly as you would locally. For example:
docker run --rm \
-e STABLY_API_KEY=$STABLY_API_KEY \
stably-tests \
--project=chromium \
--grep @critical
Everything supported by npx playwright test
works with npx stably test
, including reporters, --headed
, and configuration overrides.
Parallel Runs with Multiple Containers
Shard your suite by spinning up multiple instances of the same test image. Each container can target the same backing services or its own isolated stack, depending on how you model the compose file or orchestrator:
docker run --rm \
--network my-app-network \
-e STABLY_API_KEY=$STABLY_API_KEY \
stably-tests --shard=1/4 &
docker run --rm \
--network my-app-network \
-e STABLY_API_KEY=$STABLY_API_KEY \
stably-tests --shard=2/4 &
docker run --rm \
--network my-app-network \
-e STABLY_API_KEY=$STABLY_API_KEY \
stably-tests --shard=3/4 &
docker run --rm \
--network my-app-network \
-e STABLY_API_KEY=$STABLY_API_KEY \
stably-tests --shard=4/4 &
wait
In Compose, add separate services that share the same build target but override the command:
services:
tests-shard-1:
build:
context: .
target: tester
environment:
STABLY_API_KEY: ${STABLY_API_KEY}
command: ["npx", "stably", "test", "--shard=1/4"]
tests-shard-2:
build:
context: .
target: tester
environment:
STABLY_API_KEY: ${STABLY_API_KEY}
command: ["npx", "stably", "test", "--shard=2/4"]
# ...repeat for additional shards
Stably aggregates results from every shard automatically in the dashboard.
Persist Playwright Artifacts
Mount a volume if you want to inspect local reports in addition to the Stably dashboard:
docker run --rm \
-e STABLY_API_KEY=$STABLY_API_KEY \
-v "$(pwd)/playwright-report:/app/playwright-report" \
stably-tests \
--reporter=html
The reports folder stays in sync with your host so you can open it after the container exits.
Next Steps