Why Docker for QA
Docker solves one of QA’s oldest problems: environment inconsistency. How many times have you heard “it works on my machine” when reporting a bug? Docker eliminates this by packaging applications and their dependencies into containers that run identically everywhere.
For QA engineers, Docker provides:
- Consistent test environments across local machines, CI servers, and staging
- Isolated test execution — tests do not interfere with each other or the host system
- Reproducible bugs — if it fails in a container, it fails the same way every time
- Fast environment setup — spin up a complete test environment in seconds, not hours
Core Docker Concepts
Images
A Docker image is a lightweight, standalone package that includes everything needed to run a piece of software: code, runtime, system tools, libraries, and settings.
Think of an image as a snapshot of a configured machine. It is read-only and immutable.
# Pull an image from Docker Hub
docker pull node:20
# List local images
docker images
# Pull a specific testing image
docker pull mcr.microsoft.com/playwright:v1.40.0-focal
Containers
A container is a running instance of an image. It is isolated from the host system and other containers, but can expose ports and mount volumes for communication.
# Run a container
docker run -it node:20 bash
# Run in background (detached mode)
docker run -d -p 3000:3000 --name my-app my-app-image
# List running containers
docker ps
# Stop a container
docker stop my-app
# View container logs
docker logs my-app
Volumes
Volumes persist data beyond a container’s lifecycle. For QA, they are essential for saving test reports and sharing test data:
# Mount a local directory into a container
docker run -v $(pwd)/test-results:/app/test-results playwright-tests
# Create a named volume
docker volume create test-data
docker run -v test-data:/data my-test-image
Networks
Docker networks enable containers to communicate with each other:
# Create a network
docker network create test-network
# Run containers on the same network
docker run -d --network test-network --name db postgres:15
docker run -d --network test-network --name app my-app-image
# Containers can reach each other by name (db, app)
Building Test Images with Dockerfile
A Dockerfile defines how to build an image. Here is a Dockerfile for a test automation project:
FROM mcr.microsoft.com/playwright:v1.40.0-focal
WORKDIR /app
# Copy dependency files first (for cache efficiency)
COPY package.json package-lock.json ./
# Install dependencies
RUN npm ci
# Copy test files
COPY . .
# Default command: run all tests
CMD ["npx", "playwright", "test"]
Dockerfile Best Practices for QA
Layer ordering matters. Docker caches each layer. Put things that change rarely (base image, dependencies) first, and things that change often (test code) last:
FROM node:20-slim
# System dependencies (rarely change)
RUN apt-get update && apt-get install -y \
chromium \
&& rm -rf /var/lib/apt/lists/*
# Application dependencies (change when package.json changes)
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# Test code (changes frequently)
COPY . .
CMD ["npm", "test"]
Use .dockerignore to exclude unnecessary files:
node_modules
.git
test-results
playwright-report
*.md
Building and Running
# Build the image
docker build -t my-tests .
# Run tests
docker run my-tests
# Run specific test file
docker run my-tests npx playwright test tests/login.spec.ts
# Run with environment variables
docker run -e BASE_URL=https://staging.example.com my-tests
# Save test results to host
docker run -v $(pwd)/results:/app/test-results my-tests
Debugging Containerized Applications
QA engineers frequently need to debug applications running in Docker:
Inspecting Running Containers
# Execute a shell inside a running container
docker exec -it container-name bash
# View real-time logs
docker logs -f container-name
# Inspect container configuration
docker inspect container-name
# Check resource usage
docker stats container-name
Common Debugging Scenarios
Application not responding:
# Check if the container is running
docker ps -a
# Check logs for errors
docker logs container-name --tail 50
# Check if the port is exposed correctly
docker port container-name
Tests fail in container but pass locally:
# Run tests interactively to see the environment
docker run -it my-tests bash
# Check environment inside the container
env | sort
# Verify file permissions
ls -la /app/
# Check available memory
free -h
Exercise: Containerize a Test Suite
Given a Node.js test project with:
- Unit tests (Jest)
- E2E tests (Playwright)
- API tests (against a PostgreSQL-backed REST API)
Create a Dockerfile that can run all three types of tests.
Solution
FROM mcr.microsoft.com/playwright:v1.40.0-focal
# Install PostgreSQL client for DB setup
RUN apt-get update && apt-get install -y \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Dependencies (cached layer)
COPY package.json package-lock.json ./
RUN npm ci
# Test configuration
COPY playwright.config.ts jest.config.ts tsconfig.json ./
# Test files
COPY tests/ tests/
COPY src/ src/
# Environment defaults
ENV NODE_ENV=test
ENV CI=true
# Default: run all tests
CMD ["npm", "run", "test:all"]
Running different test types:
# All tests
docker run my-tests
# Unit tests only
docker run my-tests npm run test:unit
# E2E tests only
docker run my-tests npx playwright test
# API tests with database
docker run --network test-net \
-e DATABASE_URL=postgresql://test:test@db:5432/testdb \
my-tests npm run test:api
Docker Commands QA Engineers Use Daily
| Command | Purpose |
|---|---|
docker run | Create and start a container |
docker ps | List running containers |
docker logs | View container output |
docker exec -it | Run commands inside a container |
docker build | Build an image from Dockerfile |
docker stop / rm | Stop and remove containers |
docker images | List local images |
docker pull | Download an image |
docker cp | Copy files between host and container |
docker system prune | Clean up unused resources |
Common Docker Images for QA
| Image | Use Case |
|---|---|
mcr.microsoft.com/playwright | Playwright E2E testing with browsers |
cypress/included | Cypress E2E testing |
selenium/standalone-chrome | Selenium with Chrome |
selenium/hub + selenium/node-* | Selenium Grid |
postgres | PostgreSQL for integration tests |
redis | Redis for caching tests |
localstack/localstack | AWS service emulation |
mailhog/mailhog | Email testing |
Key Takeaways
- Docker ensures environment consistency — the same image runs identically on your laptop and in CI
- Images are blueprints, containers are instances — one image can spawn many containers
- Layer your Dockerfile efficiently — dependencies first, test code last, for optimal caching
- Use volumes for test artifacts — mount host directories to extract reports and screenshots
- Learn basic debugging commands —
docker exec,docker logs, anddocker inspectwill save you hours