Problem running Integration tests that use Docker

circle.yml
integration-tests

#1

I use Docker and Docker-Compose to run integration tests. This works well locally, however in the circle ci Step this is failing due to my test suite not being able to connect to the mongo host.

I suspect there is something weird going on due to being inside the docker container that circle provide through this step:

    - setup_remote_docker:
        docker_layer_caching: true

I see this error:

java.net.ConnectException: Connection refused

Wrapped by: com.mongodb.MongoSocketOpenException: Exception opening socket

My docker-compose looks like:

version: '3.6'

services:
  app:
    container_name: tvr-app
    environment:
      INTEGRATION_TEST: INTEGRATION_TEST
      MONGO_HOSTS: "[mongo01]"
    build:
      context: ../../../../
      dockerfile: Dockerfile
      args:
        APP_NAME: tvr-decision-engine
    volumes:
      - ./app/conf:/conf/
    depends_on:
      - mongo01

  mongo01:
    container_name: tvr-mongo-1
    image: mongo:4.0
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: password
      MONGO_INITDB_DATABASE: test
    ports:
      - "127.25.0.3:27017:27017"
    command:
      - --bind_ip
      - "127.25.0.3,mongo01"
      - --smallfiles
      - --oplogSize
      - "128"

Please help, thanks.


#2

This looks like the problem - I don’t know if you can hardwire an IP. Make the port spec just ports, and then switch to the internal DNS name tvr-mongo-1 for the Mongo host.


#3

It is possible to specify the host address IP like I have done. This is from the docker docs:

When you invoke docker run you can use either -p IP:host_port:container_port or -p IP::port to specify the external interface for one particular binding.
https://docs.docker.com/v17.09/engine/userguide/networking/default_network/binding/

And in docker compose:

This works locally. Also using the internal DNS name will not work because the tests are connecting from outside of the docker compose network when running locally.


#4

So the reason that I have:

  • setup_remote_docker:
    docker_layer_caching: true

Is because I need to be able to run docker and docker-compose. Is it worth trying to just install them as pre-run steps instead?


#5

Can you use docker executor from CircleCI? I would do docker build using setup_remote_docker first to get a container with the app code in it. The tag for the image should container the SHA of the git repo in it (i.e. my_dockerhub/my_app:${CIRCLE_SHA} Then in the next job I do this.

docker:
- image: my_dockerhub/my_app:${CIRCLE_SHA}
- image: mongo:4.0
steps:
- run: wait-for-it -h 127.0.0.1 -p 27017 -t 60

#6

Sure, but CircleCI have done a fair bit of hacking on the networking system to merge various remote sockets into a single localhost. For networking, I would not regard the Docker manual as a good guide to what can be done in CircleCI.

You can’t do that in CircleCI though (unless your tests are in a secondary remote container). A Docker (Compose) app launched in the primary container cannot expose ports (it would require security permissions that could compromise other customers).

So, either you could run your DC app in two modes (requiring the tests to be within DC for remote and allowing them to be external for local) or just use one mode (putting the tests inside a DC container). I prefer the latter approach, personally.


#7

https://discuss.circleci.com/t/accessing-docker-container-ports/11634/2?u=msinton


#8

Thanks halfer, that was really useful info.

I have gone with the approach of running the tests in a new container. However this is not working as this container does not have a docker daemon. So I get this exception:

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

My job looks like:

   integration_tests:
     <<: *defaults
    
   docker:
      - image: circleci/openjdk:8-jdk
        environment:
          JVM_OPTS: -Xmx3200m
          TERM: dumb
          WORKSPACE_ROOT: *workspace_root

    steps:
      - setup_remote_docker:
          docker_layer_caching: true

      - *attach_workspace

      - *move_files_to_home

      - restore_cache:
          key: '{{ .Environment.CIRCLE_PROJECT_REPONAME }}-{{ arch }}-{{ checksum "build.sbt"}}-dependencies'

      - run:
          name: integration tests
          command: |
            docker create --name tests circleci/openjdk:8-jdk /bin/sh -c "cd /tvr && sbt it:test"
            docker cp $WORKSPACE_ROOT tests:/tvr
            echo "starting tests container"
            docker start -a -i tests

Normally I would fix this by mounting /var/run/docker.sock, but I have seen that it is not possible to mount volumes in circle in this setup. What should I do?


#9

Ah, right. I assumed you must have installed Docker into your build (first) container, since you showed a docker-compose.yml file, and that won’t work unless Docker and Docker Compose is installed. Am I right in assuming you have not had this running at all in CircleCI? This config file is not read by CircleCI itself.


#10

Thanks halfer

I have resolved the problem, I needed to set the network on the container.

docker create --network env_default --name tests ....

Cheers


closed #11

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.