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.