-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
My organization is running Jenkins build jobs in Docker. That makes configuring Jenkins a lot simpler; there's only one typeof build node regardless of what you're building.
However, I've run into some problems when triggering testcontainers from inside Docker.
- Issue with getContainerIpAddress(). If you are talking to Docker over a socket, DockerClientConfigUtils assumes the address of the Docker host is "localhost". That's not accurate if the test is running inside a container. (This scenario shows up when you give your container access to Docker by exposing the Docker socket as a volume.)
This issue is fixable. First, you need to detect if the test is running inside Docker. For that, you can look to see if the file "/.dockerenv" exists - inside a container, it is always present. Second, you need to know what IP to provide in that case. Luckily, you don't need the IP of the docker host; the default gateway (usually 172.17.0.1) is normally sufficient. You can get this by running "netstat -nr" and parsing the output. (That may vary with more complex networking scenarios.)
If there's interest, and the approach seems palatable, I can assemble a pull request for this.
- Issue with the way Docker does port mapping. Take a look at this. I've verified this behavior in Docker 1.10 on OSX docker-machine and on a pure Ubuntu host with Docker 1.9.
# get your docker IP (change for your docker setup)
DOCKER_IP=`docker-machine ip docker-vm`
# run a container that maps port 9999, but doesn't listen on it.
docker run -d -name dummy -p 9999:80 alpine:3.3 /bin/sh sleep 1000
# try to connect to it; fails and returns right away
nc -v $DOCKER_IP 9999
# try to connect to it from inside another container
docker run --rm -it alpine:3.3 nc -v $DOCKER_IP 9999
The final nc command will connect to the socket and just sit there. That's right, for some reason Docker is accepting connections on the mapped port, even though there's nothing listening. If you try to do anything with the port, you'll get "connection reset by peer" or other error. (I'm not sure if this is intended behavior on the Docker side or an accident; I haven't dug in that deeply.)
This behavior significantly breaks the container startup flow in GenericContainer. There, we consider the container to have started as soon as we can get a socket connection to the port. Sadly, the "new Socket().close()" code there is just as fooled as "nc", so it can proceed to testing with a not-yet-functional container.
Obviously, a Thread.sleep() call at the top of a test is a (bad) workaround for this. The changes in pull request 113 would provide a solution for most users out-of-the-box, and will allow developers who are testing non-http services to write their own wait strategies.