
Elevate Your CI/CD: Dockerized E2E Tests with GitHub Actions
End-to-end testing is a critical aspect of software development that tests a workflow from start to finish, guaranteeing that the system and its components function together as expected. This article details the process of setting up a GitHub Actions pipeline for end-to-end testing an Express and React app by spinning up a local environment using Docker Compose, and executing dockerized Playwright tests against that local environment.
Explore the sample repository on Github: Docker Express React Sample Repo
1. Project Overview
Our setup consists of five key components:
- An Express-powered Node.js backend.
- A frontend built on the React framework.
- Docker Compose for initializing the local environment.
- Playwright for performing E2E testing.
- GitHub Actions for conducting automated Continuous Integration (CI) tests.
2. Dockerization of Express and React Applications
The first step involves creating Dockerfiles for both the Express and React applications. Each Dockerfile contains necessary instructions to build a Docker image for its respective application.
2a. Express App Dockerfile
This Dockerfile begins from a base Node.js image, copies application files into the container, installs dependencies using Yarn, compiles the application, and lastly, specifies the command to launch the Express app.
2b. React App Dockerfile
The Dockerfile for the React application is similar to the Express Dockerfile, with the key difference being the start command. Since React apps compile into static files served by a web server, they lack a Node.js entry point like Express apps. Hence, ‘yarn start’ is used as the start command to trigger Create React App’s development server.
3. Setting Up Local Environment with Docker Compose
We use Docker Compose to spin up a local environment that consists of both the Express and React apps. We define a docker-compose.yaml
file, where we describe the services (Express and React apps) to be created, including the custom container names, build context directories, Dockerfile locations, and port mappings.
4. Configuring Playwright for E2E Testing
Next, we dockerize our Playwright tests. The Dockerfile will start with Node.js and Playwright images, copy the test files into the container, install the necessary dependencies, and install system dependencies and the Playwright CLI. This setup assumes that the Dockerfile, Playwright config file, and the tests are all within the same directory.
The Playwright configuration file playwright.config.ts
configures the testing environment, including execution settings (like timeout, retries, workers), the viewport size, video recording, and the base URL for testing.
5. Implementing the GitHub Actions Pipeline
The final step involves setting up a GitHub Actions pipeline. Defined in .github/workflows/e2e-tests.yml
, the pipeline is triggered every time a pull request is made to the ‘main’ branch or when manually instigated. The pipeline checks out the repository, launches the local environment with Docker Compose, builds the Docker image for E2E tests, executes the tests against the local environment, and finally, uploads the container logs, test reports, and video recordings as artifacts.
Now create a pull request against the main branch to execute your E2E Test pipeline.

Once complete, navigate to the summary tab to download your pipeline artifacts, including:
- Logs for the backend, frontend, and e2e containers
- The E2E Test report, which includes video recordings for each test

Now, you’re set to automatically test your applications end-to-end whenever necessary, ensuring that your system functions as expected in a production-like environment. This workflow will help you catch bugs and issues early before they reach your users.