Accessing custom service

I’m trying to set up a custom service to run along side my tests and I’m failing to connect the dots. I have a drone.yml that looks something like this:

pipeline:
  test:
    image: anonymized/drone-base:latest
    commands:
      - python -c "import socket; sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM); print sock.connect_ex(('127.0.0.1', 8077))"

services:
  datastore:
    image: anonymized/datastore-emulator:latest

The Dockerfile for the datastore-emulator image looks like this:

FROM anonymized/drone-base:latest

RUN apt-get install -y default-jre

# Running the emulator requires this
ENV CLOUDSDK_CORE_PROJECT anonymized

RUN gcloud components install beta cloud-datastore-emulator --quiet

ENTRYPOINT ["gcloud"]
CMD ["beta", "emulators" ,"datastore", "start", "--consistency=1.0", "--no-store-on-disk", "--host-port=127.0.0.1:8077"]

As far as I can tell, this image runs fine in a container. Drone shows datastore service started at 127.0.0.1:8077 but somehow it is not accessible. My poor man’s port probe above is supposed to verify that. This gives me a 111 socket response (connection refused).

What am I missing? Are there any particular requirements for how the service container should be set up? Anything about the network setup I should know?

You need to access the service by its hostname, not by the loopback address (127.0.0.1). You can see some examples in the docs here:

http://docs.drone.io/services/
http://docs.drone.io/redis-example/
http://docs.drone.io/mysql-example/

Thanks, I got this part to work. I think the documentation isn’t quite clear that the service needs to bind to the hostname derived from the service name.

So now the fun part: My tests are actually run inside an image that’s built in the previous build step. So it looks something like this (heavily simplified):

  build:
    image: anonymized/drone-base:latest
    commands:
      - docker build -t anonymized/${DRONE_REPO_NAME}:${DRONE_COMMIT} .
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
  test:
    image: anonymized/drone-base:latest
    commands:
      - docker run -t anonymized/${DRONE_REPO_NAME}:${DRONE_COMMIT} bash -c "nosetests"

Obviously this way tests cannot access the service running at datastore:8077 in the “parent” container. I tried a bunch of different things which didn’t work:

docker run --network=host -t anonymized/${DRONE_REPO_NAME}:${DRONE_COMMIT} bash -c "DL_DATASTORE_EMULATOR_HOST=datastore nosetests"
docker run --network=host -t anonymized/${DRONE_REPO_NAME}:${DRONE_COMMIT} bash -c "DL_DATASTORE_EMULATOR_HOST=\$(route | awk '/^default/ { print \$2 }') nosetests"

Obviously I barely know what I’m doing here. Is there any way to make this work?

this instead:

  build:
    image: anonymized/drone-base:latest
    commands:
      - docker build -t anonymized/${DRONE_REPO_NAME}:${DRONE_COMMIT} .
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
  test:
    image: anonymized/${DRONE_REPO_NAME}:${DRONE_COMMIT}
    commands:
      - cd /path/to/your/code
      - nosetests

the difference is that you are letting drone create the test container, which means it will be added to the correct bridge network and will have access to the service containers.