> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stably.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Run Tests Inside of Docker

> Containerize Stably-powered Playwright tests for reproducible local and CI execution.

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](/stably-cli/run-tests) and the [GitHub Actions setup](./run-tests-on-github)--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 20+ 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:

```Dockerfile Dockerfile theme={null}
FROM node:20-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 stably 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

```bash theme={null}
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:

```bash theme={null}
docker run --rm \
  --network my-app-network \
  -e STABLY_API_KEY=$STABLY_API_KEY \
  -e STABLY_PROJECT_ID=$STABLY_PROJECT_ID \
  -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.

<Note>
  Store your Stably API key securely--use environment files, Docker secrets, or your orchestrator's secret manager instead of hardcoding it in the image.
</Note>

## 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.

```yaml docker-compose.yml theme={null}
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}
      STABLY_PROJECT_ID: ${STABLY_PROJECT_ID}
      BASE_URL: http://web:3000
    command: ["npx", "stably", "test"]
```

Run everything together and exit with the test result:

```bash theme={null}
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:

```bash theme={null}
docker run --rm \
  -e STABLY_API_KEY=$STABLY_API_KEY \
  -e STABLY_PROJECT_ID=$STABLY_PROJECT_ID \
  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:

```bash theme={null}
docker run --rm \
  --network my-app-network \
  -e STABLY_API_KEY=$STABLY_API_KEY \
  -e STABLY_PROJECT_ID=$STABLY_PROJECT_ID \
  stably-tests --shard=1/4 &

docker run --rm \
  --network my-app-network \
  -e STABLY_API_KEY=$STABLY_API_KEY \
  -e STABLY_PROJECT_ID=$STABLY_PROJECT_ID \
  stably-tests --shard=2/4 &

docker run --rm \
  --network my-app-network \
  -e STABLY_API_KEY=$STABLY_API_KEY \
  -e STABLY_PROJECT_ID=$STABLY_PROJECT_ID \
  stably-tests --shard=3/4 &

docker run --rm \
  --network my-app-network \
  -e STABLY_API_KEY=$STABLY_API_KEY \
  -e STABLY_PROJECT_ID=$STABLY_PROJECT_ID \
  stably-tests --shard=4/4 &

wait
```

In Compose, add separate services that share the same build target but override the command:

```yaml docker-compose.yml theme={null}
services:
  tests-shard-1:
    build:
      context: .
      target: tester
    environment:
      STABLY_API_KEY: ${STABLY_API_KEY}
      STABLY_PROJECT_ID: ${STABLY_PROJECT_ID}
    command: ["npx", "stably", "test", "--shard=1/4"]
  tests-shard-2:
    build:
      context: .
      target: tester
    environment:
      STABLY_API_KEY: ${STABLY_API_KEY}
      STABLY_PROJECT_ID: ${STABLY_PROJECT_ID}
    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:

```bash theme={null}
docker run --rm \
  -e STABLY_API_KEY=$STABLY_API_KEY \
  -e STABLY_PROJECT_ID=$STABLY_PROJECT_ID \
  -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

* Wire up [Slack notifications](/integrations/slack) for containerized runs
* Review [GitHub integration](/integrations/github) for PR status checks and annotations
