Docker packages an application and its dependencies into a repeatable environment. For QA automation, this helps the same tests run locally and in CI with fewer environment differences.
Core concepts
A read-only package containing the files and dependencies needed to run something.
A running instance of an image. Containers can be created, stopped and removed.
A text file with instructions for building an image.
A service that stores images, such as Docker Hub or a private company registry.
Storage mounted into a container. It can persist data or expose reports to the host.
A YAML file that defines and runs one or more related containers.
Common Docker commands
| Command | Use |
|---|---|
docker --version | Check that Docker is installed. |
docker pull image:tag | Download an image. |
docker images | List local images. |
docker build -t qa-tests . | Build and name an image from the current folder. |
docker run --rm qa-tests | Run a container and remove it when it stops. |
docker ps | List running containers. |
docker ps -a | List all containers. |
docker logs container-name | Show container output. |
docker exec -it container-name sh | Open a shell inside a running container. |
docker stop container-name | Stop a running container. |
docker rm container-name | Remove a stopped container. |
docker rmi image-name | Remove a local image. |
Understand a Dockerfile
FROM node:22-bookworm
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["npm", "test"]
| Instruction | Meaning |
|---|---|
FROM | Selects the base image. |
WORKDIR | Sets the current folder inside the image. |
COPY | Copies files from the build context into the image. |
RUN | Runs a command while building the image. |
CMD | Defines the default command when the container starts. |
docker build. A container is created from that image by docker run.Playwright project example
This minimal TypeScript project runs one Playwright test inside Docker.
Project structure
playwright-docker-example/
├── tests/
│ └── example.spec.ts
├── .dockerignore
├── Dockerfile
├── package.json
├── package-lock.json
└── playwright.config.ts
1. package.json
{
"name": "playwright-docker-example",
"private": true,
"scripts": {
"test": "playwright test"
},
"devDependencies": {
"@playwright/test": "1.62.0"
}
}
Run npm install once locally to generate package-lock.json.
2. playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
reporter: [['list'], ['html', { open: 'never' }]],
use: {
baseURL: 'https://example.com',
trace: 'retain-on-failure',
screenshot: 'only-on-failure'
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }
]
});
3. tests/example.spec.ts
import { test, expect } from '@playwright/test';
test('example page has the correct title', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveTitle(/Example Domain/);
await expect(page.getByRole('heading')).toHaveText('Example Domain');
});
4. Dockerfile
FROM mcr.microsoft.com/playwright:v1.62.0-noble
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["npx", "playwright", "test"]
5. .dockerignore
node_modules
playwright-report
test-results
.git
.env
*.log
package.json should match the Docker image version. Update both together when the project is upgraded.Build and run the tests
# Build the image
docker build -t playwright-tests .
# Run the tests
docker run --rm --init --ipc=host playwright-tests
Save the HTML report on your computer
Mount the report folder when starting the container.
docker run --rm --init --ipc=host \
-v "$(pwd)/playwright-report:/app/playwright-report" \
playwright-tests
On PowerShell, replace $(pwd) with ${PWD}.
Pass a base URL at runtime
Use an environment variable in the Playwright configuration:
baseURL: process.env.BASE_URL || 'https://example.com'
Then run:
docker run --rm --init --ipc=host \
-e BASE_URL=https://test.example.com \
playwright-tests
Docker Compose
Compose is useful when tests need an application, API or database container.
services:
web:
image: nginx:alpine
ports:
- "8080:80"
tests:
build: .
environment:
BASE_URL: http://web
depends_on:
- web
# Build and run the services
docker compose up --build --abort-on-container-exit
# Stop and remove the services
docker compose down
depends_on controls start order, but it does not guarantee that the application is ready. Use a health check or retry strategy for real projects.Practical QA uses
- Run the same browser and dependency versions locally and in CI.
- Create a clean test environment for each execution.
- Run API mocks, databases and the application with Compose.
- Reproduce an environment-specific automation failure.
- Share a ready-to-run automation setup with another tester.
- Run tests in parallel using separate containers or CI jobs.
Common problems
| Problem | Check |
|---|---|
| Browser executable not found | Confirm that project and Docker image Playwright versions match. |
| Application is unreachable | Inside a container, localhost means that container. Use the Compose service name or the correct host address. |
| Reports disappear | Mount the report folder as a volume. |
| Build is slow | Copy dependency files and run npm ci before copying frequently changed project files. |
| Tests fail only in Docker | Compare environment variables, URLs, permissions, CPU, memory and browser versions. |