Docker IP + tests scenario failing

I’m trying to use the following instructions:

version: 2
jobs:
  build:
    working_directory: ~/repo
    docker:
      - image: docker:17.05.0-ce-git
      - image: circleci/node:9.4.0
      
    steps:
      - checkout
      - setup_remote_docker
      - run: docker build -t auth0-express-api-rs256 .
      - run: 
           name: background server
           command: |
               docker run --env-file .env -p 3010:3010 -it auth0-express-api-rs256
           background: true
      - run: sleep 10
      - run: curl -i http://localhost:3010/api/public

But I’m getting an error as the dockerized version of my app is not running on localhost:3010, is there any additional configuration that I need to perform so that the background server can run on localhost:3010? or am I missing some concepts that I need to consider?

It should be OK. What is the console output for the docker run step? Also, what do you get if you do docker ps in a separate run after the sleep?

It may be worth doing an ls as well, to see if the .env is in the cwd. I assume that’s in your checkout? Examining the output for the docker run should identify if there are any start-up problems here.

What error are you getting?

I’m sorry, I’ve omitted some steps but this is the full script for my build:

version: 2
jobs:
  build:
    working_directory: ~/repo
    docker:
      - image: circleci/node:9.4.0
      - image: docker:17.05.0-ce-git
      
    steps:
      - checkout
      - setup_remote_docker
      - run: 
          name: Set .env file with useful variables
          command: |
              echo "DOMAIN=$domain" >> .env
              echo "NAME=$audience" >> .env
          
      - run: docker build -t auth0-express-api-rs256 .
      - run: 
           name: background server
           command: docker run --env-file .env -p 3010:3010 -it auth0-express-api-rs256
           background: true
           
      - run: sleep 15
      - run: docker ps
      - run: curl -i http://localhost:3010/api/public

The current output of the docker run step is:

docker run --env-file .env -p 3010:3010 -it auth0-express-api-rs256
^@^@npm info it worked if it ends with ok
npm info using npm@5.4.2
npm info using node@v8.7.0
npm info lifecycle authenticate-rs256@0.0.0~prestart: authenticate-rs256@0.0.0
npm info lifecycle authenticate-rs256@0.0.0~start: authenticate-rs256@0.0.0

> authenticate-rs256@0.0.0 start /home/app
> node server.js

Listening on http://localhost:3010
Step was canceled

The result of the docker ps is:

#!/bin/bash -eo pipefail
docker ps
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS              PORTS                    NAMES
71884731ff75        auth0-express-api-rs256   "npm start"         15 seconds ago      Up 14 seconds       0.0.0.0:3010->3010/tcp   keen_blackwell

and the error I’m getting is with the curl step:

curl -i http://localhost:3010/api/public
curl: (7) Failed to connect to localhost port 3010: Connection refused
Exited with code 7

That’s what makes me wonder if the ip of the docker machine is different than localhost

Yep, good thinking. The Circle infrastructure does spin up its own containers over different machines, maybe it affects docker run directly? One thing you can do is install Docker Compose, and then have two containers: one for your Express app and one for curl/tests etc. It’s what I do, and it works very well. You no longer use localhost; DC sets up a LAN between containers, and you just use the container name.

I can paste some install config if that is useful, if you are happy to use DC.

Incidentally I don’t think you need the Docker image:

docker:
  - image: circleci/node:9.4.0
  - image: docker:17.05.0-ce-git

Commands in Circle are run in the first named container, so I think the second container is spinning up and not doing anything. I presume that the Docker client is installed in the Node image?

Thanks for the clarification, I was currently trying to get the IP of the container using docker inspect <container> and then I’ll be able to curl to that IP, It’ll sure be useful if you can give me that example of the DC install config and try use that solution too.

Ah good idea, try that first. I wonder however whether firewalling within Circle would block arbitrary ports by default. Ping me if that doesn’t work.

Edit: ah, I spotted that in your configs above, in one case you have docker:17.05.0-ce-git as your first container, and in another you have it as your second. They will do very different things. If you need both Docker and NPM in one container, pick one and install the other thing with apt :smile_cat:

Aha, also see this.

You can start up a container and then run curl remotely through it.

I was able to obtain the container IP using docker inspect --format '{{ .NetworkSettings.IPAddress }}' container-name, but if I curl to that address on a separate step I still get the same error.

I also read your last response regarding the accessing services, I tried doing:

- run: 
           name: background server
           command: |
              docker run --name rafa-test --env-file .env -p 3010:3010 -it auth0-express-api-rs256 
              docker exec rafa-test curl -i http://localhost:3010/api/public

But the step gets stuck on the execution(maybe because the run starts an express server), any suggestions?

It looks like you’re running inside the thing you are testing. That’s not necessarily bad, but it’s worth checking to see if this is possible. Run an SSH on your failing build, get yourself a shell, then try this:

docker exec -it rafa-test sh

That will give you a shell into your running container. Then try your curl. If that works, then maybe you need to sleep between the run and the curl, to give Express time to settle.

@halfer I was able to solve all this problem by switching the executor type to “machine: true” though I had to modify a litle the test-script due to the fact that the machine executor only has node until 6.1 version

1 Like

That’s avoiding the problem, not solving it :smile_cat: - though I accept that may be “good enough”.

The machine executor is guaranteed to keep its containers on one box (and you get more memory to play with) but it is slower than Docker, and you may be charged extra for the facility in the future.