0
votes

I'm trying to run Cypress tests from Docker container with this in the Dockerfile:

FROM cypress/included:4.8.0

WORKDIR /usr/src/app

ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY cypress.json /usr/src/app/cypress.json

I spin all my containers with docker-compose up -d --build and they're running just fine but when I try to run basic Cypress test with: docker run -it -v $PWD:/services/cypress -w /usr/src/app --entrypoint=cypress tdd_cypress run

I get:

Cypress could not verify that this server is running:

  > http://nginx:80

We are verifying this server because it has been configured as your `baseUrl`.

Cypress automatically waits until your server is accessible before running tests.

We will try connecting to it 3 more times...
We will try connecting to it 2 more times...
We will try connecting to it 1 more time...

Cypress failed to verify that your server is running.

Please start this server and then run Cypress again.

Here's my docker-compose file:

version: '3.7'

services:

  users:
    container_name: flask
    build:
      context: ./services/users
      dockerfile: Dockerfile
    volumes:
      - './services/users:/usr/src/app'
    ports:
      - 5001:5000
    environment:
      - FLASK_ENV=development
      - APP_SETTINGS=project.config.DevelopmentConfig
      - DATABASE_URL=postgres://postgres:postgres@users-db:5432/users_dev
      - DATABASE_TEST_URL=postgres://postgres:postgres@users-db:5432/users_test
      - SECRET_KEY=python_rocks
    depends_on:
      - users-db

  users-db:
    container_name: postgres
    build:
      context: ./services/users/project/db
      dockerfile: Dockerfile
    ports:
      - 5436:5432
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres

  client:
    container_name: react
    build:
      context: ./services/client
      dockerfile: Dockerfile
    volumes:
      - './services/client:/usr/src/app'
      - '/usr/src/app/node_modules'
    ports:
      - 3007:3000
    environment:
      - NODE_ENV=development
      - REACT_APP_USERS_SERVICE_URL=${REACT_APP_USERS_SERVICE_URL}
    depends_on:
      - users

  nginx:
    container_name: nginx
    build:
      context: ./services/nginx
      dockerfile: Dockerfile
    restart: always
    ports:
      - 80:80
    depends_on:
      - users
      - client

  cypress:
    container_name: cypress
    build:
      context: ./services/cypress
      dockerfile: Dockerfile
    depends_on:
      - nginx
      - users
      - client

I found very similar topic here and the solution is pretty much the same like the one below but my Cypress instance keeps timing out.

UPDATE:

After receiving feedback from others I edited Cypress service within Docker-Compose to make it look like this:

cypress:
    container_name: cypress
    ipc: host
    network_mode: host
    build:
      context: ./services/cypress
      dockerfile: Dockerfile

and baseUrl is set to http://nginx:80 and also tried http://client:3007. Sadly, either way it had no effect on the error. I've ran docker-compose up -d --build to ensure changes take effect.

Is there any good reason for Cypress not being able to access the Nginx on the port 80 ? Any feedback much appreciated.

2
Each container has its own localhost, so Cypress is trying to connect to itself. Networking in Compose describes the overall network environment your containers will see and how to connect from one container to another.David Maze
@DavidMaze OK, my apologizes, I wasn't specific enough. I meant the localhost on Nginx container because it's a proxy that routes all the traffic and it listens on the port 80. Hence I need Cypress container to be able to access the port 80 on Nginx.road_runner

2 Answers

1
votes

So, eventually what I did I think of as workaround. Instead of begging Cypress to recognize service that's running right next to it and run tests on it, I took a different approach. I knew that Nginx container has an assigned IP on my local computer so what I did I look it up using ifconfig in my case it spat out:

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:9eff:fe60:ffea  prefixlen 64  scopeid 0x20<link>
        ether 02:42:9e:60:ff:ea  txqueuelen 0  (Ethernet)
        RX packets 95725  bytes 6812024 (6.8 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 126972  bytes 163560616 (163.5 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

and I grabbed the IPv4 address and put it into cypress.json to make it read like this:

{
  "baseUrl": "http://172.17.0.1",
  "video": false
}

and I don't need to specify port 80 because it's picked by default if you don't specify it. On production I did the same but used a production server IP instead of dev one.

Admittedly, this isn't the most elegant solution but it works and if anyone finds nicer solution to this please do share. I'd love to hear about it and learn.

0
votes

First of all this is neither cypress issue nor docker issue. You are using it incorrectly when you are using in docker-compose. When you are spinning up the local environment with docker-compose and if you say localhost, your docker doesn't know which is localhost as multiple services running within that.... If you want to talk to other service, you have to provide it's service name.

You have to provide the service name of your application i.e. in your case

Solution: http://nginx. For reference refer the below compose snippet.

frontend-app:
    container_name: frontend-app
    build:
      context: ./services/frontend-repo
      dockerfile: Dockerfile
    restart: always
    ports:
      - 80:80

  cypress:
    container_name: cypress
    build:
      context: ./services/cypress
      dockerfile: Dockerfile
    depends_on:
      - frontend-app

In this case, you have to open http://frontend-app