Running cypress tests with java backend

Hi!

I tried a lot in the past few days with circleci and my config.yml. Right now I can run my frontend tests and my backend tests, save the test results etc. I also can build my docker container and deploy it later to heroku and this works great too.
I added cypress for end2end tests in my project and tried to run it on circleci today. I know that I need to run my backend at some point and have a cypress docker image and run cypress tests. The problem is that I dont quite understand what the best way is to run the backend?

I tried this but couldnt make it work because I dont get how my image should have access to the myapp.jar? I have the jar in the workspace, is there a way to access it there?

docker:
  - image: cypress/browsers:chrome67
  - image: gradle:jdk8
    name: test
    command: java -server -jar myapp.jar
steps:
   - run:
      name: Run cypress
      command: |
        cd frontend && npm run cypress:run

If this is the wrong way, can I somehow run my docker container which exposes my backend at localhost:8080 and then run a cypress container which has access to it? How would I do that?

Thanks for the help.

I don’t quite understand your architecture, but I can give some broad advice.

You can certainly run Docker containers in CircleCI. If you want to run several containers and network them together, try Docker Compose. Rather than running them in the CircleCI Docker infra, run them inside your build container. You can’t publish ports to the host in Docker for security reasons, but if everything that needs to connect to something is in a container, you don’t need to publish to the host - containers can see each other without that.

Thanks for your input.

Im actually trying something like this:

  - setup_remote_docker
  - run:
      name: Load docker image from .tar file
      command: |
        docker load -i myapp.tar
  - run: 
      name: Run app
      command: |
        docker run -d -it -p 8080:8080 myapp
  - run:
      name: install-npm
      command: |
        cd myapp-frontend && npm install
  - run:
      name: Run cypress
      command: |
        cd myapp-frontend && npm run cypress:run

In the log I see the backend starting but my cypress cant find it at localhost:8080. I guess probably I cant access the docker running remotely (?) from cypress running in the primary container? Is it the problem you described?

Correct. In CircleCI, you cannot publish ports like so:

This is a security restriction - if you could publish ports, you would also have permissions to affect the networking stack that would affect other customers on the Docker host.

To solve it, create a docker-compose.yml file and define two services: one for myapp and the other for cypress. Compose will automatically create a virtual network between the two, and each one will have a magic DNS entry created (so the Cypress service will be able to connect to myapp by name).

For completeness, I might note that you can specify networking options using docker run, so you don’t strictly need Docker Compose. However, it is probably easier to use Compose - your YAML config will probably only need to be ~15 lines long.

I appreciate the help and will try to do it with docker compose :slight_smile:

1 Like

Thanks for the help again. I tried it with docker-compose and locally it works. Starts my backend and runs the cypress tests :slight_smile: didnt get it to work on circleci atm tho. If I dont include network_mode: 'host' in my docker-compose.yml my cypress cant find the running backend and as soons as I include it I have errors like that:

cypress_1  | Xvfb exited with a non zero exit code.
cypress_1  | 
cypress_1  | There was a problem spawning Xvfb.
cypress_1  | 
cypress_1  | This is likely a problem with your system, permissions, or installation of Xvfb.
cypress_1  | 
cypress_1  | ----------
cypress_1  | 
cypress_1  | Error: _XSERVTransSocketINETCreateListener: ...SocketCreateListener() failed
cypress_1  | _XSERVTransMakeAllCOTSServerListeners: server already running
cypress_1  | (EE) 
cypress_1  | Fatal server error:
cypress_1  | (EE) Cannot establish any listening sockets - Make sure an X server isn't already running(EE)

Didnt find a solution for that atm.

I don’t think you need network_mode to set up a basic network inside DC. You don’t even need to declare a network - it is automatic. Paste your docker-compose.yml here if you want readers to help with it.

The only other remark I would offer is that this probably isn’t a CircleCI issue per se - screen buffers are notoriously fiddly on non-desktop machines, and I generally think of this as a common-or-garden Linux problem. Search for the error message to find potential solutions.

version: '3'
services:
 backend:
  build:
    context: .
    dockerfile: Dockerfile
  ports:
    - "8080:8080"
  environment:
    - some envs...
 cypress:
   build:
     context: .
     dockerfile: Dockerfile.cypress
   depends_on:
      - "backend"
   network_mode: 'host'
   command: npm run cypress:run

I have a Dockerfile and Dockerfile.cypress. Locally it works. If I remove the network_mode cypress searches the backend at localhost:8080 and cant find it.

My Dockerfile.cypress looks like that

FROM cypress/base:10

WORKDIR /app

COPY ./frontendstuff .

RUN npm ci

RUN npm run cypress:verify

Error I get on circleci

cypress_1  | Xvfb exited with a non zero exit code.
cypress_1  | 
cypress_1  | There was a problem spawning Xvfb.
cypress_1  | 
cypress_1  | This is likely a problem with your system, permissions, or installation of Xvfb.
cypress_1  | 
cypress_1  | ----------
cypress_1  | 
cypress_1  | Error: _XSERVTrans
cypress_1  | SocketUNIXCreateListener: ...SocketCreateListener() failed
cypress_1  | 
cypress_1  | _XSERVTrans
cypress_1  | MakeAllCOTSServerListeners: server already running
cypress_1  | 
cypress_1  | (EE)
cypress_1  | 
cypress_1  | 
cypress_1  | Fatal server error:
cypress_1  | 
cypress_1  | (EE)
cypress_1  | 
cypress_1  | Cannot establish any listening sockets - Make sure an X server isn't already running
cypress_1  | (EE)

Running it on my mac works fine tho…probably not a cypress problem.

You don’t need to publish ports, and I don’t think CircleCI will allow it either - that is the same security restriction as before. Remove the port publishing, and connect to http://backend:8080 instead. I mentioned this earlier (“containers can see each other without that”).

Remove the network_mode too.