How to check if application has started inside container
But with version 1.7.1 ports are instantly available, before application has even started inside container.
I don't think that's true -- that is, I think it depends on how you are trying to contact a port. Consider, for example, a container like this:
$ docker run -it -p 8888:80 alpine sh
Here we've set up port forward from host port 8888 to container port 80, but we haven't set up anything to listen inside the container. Trying to connect to port 8888 on localhost
results in a successful connection that immediately closes:
$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
Which is exactly what you are experiencing. But if instead of localhost
we use an ip address of the host, we see different behavior:
$ telnet 192.168.1.55 8888
Trying 192.168.1.55...
telnet: connect to address 192.168.1.55: Connection refused
If inside the container I start a web server:
/ # apk add mini_httpd
[...]
/ # mini_httpd
mini_httpd: started as root without requesting chroot(), warning only
Then I can successfully connect:
$ telnet 192.168.1.55 8888
Trying 192.168.1.55...
Connected to 192.168.1.55.
Escape character is '^]'.
This happens because connections via localhost
are handled by the Docker userland proxy, which is bound to port 8888:
# netstat -tlnp | grep 8888
tcp6 0 0 :::8888 :::* LISTEN 2809/docker-proxy
But connections to another interface ip -- and any connection originating from another host -- will be handled by the rules in the iptables nat
table:
# iptables -t nat -S DOCKER
-N DOCKER
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8888 -j DNAT --to-destination 172.17.0.138:80
Or is there other reliable method to check if application has started inside container?
You have a few choices:
Just connect to the container ip directly, rather than relying on port forwarding. E.g., in the above example the container I started was assigned address 172.17.0.138. I can just connect to that instead of a host address. It's easy to find the ip address of a docker container:
$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' my-container 172.17.0.138
Wait until you achieve a successful connection to your application. In this example, in which I ultimately started a web server, I could wait until
curl
successfully connects:while ! curl -sf http://localhost:8888/; do sleep 1 done
The
-f
flag tells curl to exit with an error code if it cannot successfully fetch a URL.