Run Cypress included from Docker container

How to test web application running on localhost using Cypress running inside a Docker container

In the blog post "Run Cypress with a single Docker command" I gave several examples running Cypress Docker image cypress/included using docker-compose command. I also showed how to run Cypress inside a Docker container, yet see it on the host machine. But I did not give an example of how to run Cypress inside a Docker container and test a web application running on the host machine.

In this short blog post I will show how to do this. I am running Docker v18.09.2 on Mac.

So imagine I have a local web application running on localhost:3333. For example it could be a http-server serving a local public folder:

1
http-server -p 3333 public

I can load http://localhost:3333 in any browser and see the page.

My cypress.json file points at this URL

cypress.json
1
2
3
{
"baseUrl": "http://localhost:3333"
}

Typically I would install Cypress locally, but maybe I don't want to install any tools. I can still run cypress/included Docker image, but any application running inside the container does NOT have access to the localhost of the host machine. Instead Docker provides a special hostname host.docker.internal for container processes to access the web apps running on the host machine, see this Stackoverflow question. When I start Cypress run, I need to set the base url config parameter, which I will do using an environment variable CYPRESS_baseUrl. Here is the full command with explanation below

1
2
3
4
5
docker run -it \
-v $PWD:/e2e \
-w /e2e \
-e CYPRESS_baseUrl=http://host.docker.internal:3333 \
cypress/included:3.3.1
1
2
3
4
5
6
7
Explanation of the "docker run" command line arguments:

-it = interactive terminal
-v $PWD:/e2e = map current folder to /e2e inside the container
-w /e2e = set working directy to /e2e
-e CYPRESS_baseUrl=... = pass environment variable CYPRESS_baseUrl
cypress/included:3.3.1 = name of the Docker image with tag

The tests run and finish

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
====================================================================================================

(Run Starting)

┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Cypress: 3.3.1 │
│ Browser: Electron 61 (headless) │
│ Specs: 1 found (spec.js) │
└────────────────────────────────────────────────────────────────────────────────────────────────┘


────────────────────────────────────────────────────────────────────────────────────────────────────

Running: spec.js... (1 of 1)


✓ loads page (291ms)

1 passing (320ms)


(Results)

┌─────────────────────────┐
│ Tests: 1 │
│ Passing: 1 │
│ Failing: 0 │
│ Pending: 0 │
│ Skipped: 0 │
│ Screenshots: 0 │
│ Video: true │
│ Duration: 0 seconds │
│ Spec Ran: spec.js │
└─────────────────────────┘


(Video)

- Started processing: Compressing to 32 CRF
- Finished processing: /e2e/cypress/videos/spec.js.mp4 (0 seconds)


====================================================================================================

(Run Finished)


Spec Tests Passing Failing Pending Skipped
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ✔ spec.js 318ms 1 1 - - - │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
All specs passed! 318ms 1 1 - - -

Bonus

You can use cypress/included on CI server, see bahmutov/cypress-included-example for example.