Pavan Keerthi
Pavan Keerthi

Reputation: 1681

How to add a docker health check to test a tcp port is open?

I have a server which is running an apache hive service on port 9083. The thing is it doesn't support http protocol (but uses thrift protocol).so I can't simply add

HEALTHCHECK CMD http://127.0.0.1:9083 || exit 1 #  this check fails

All I want is to check if that port is open. I have netstat and curl on server but not nc.

So far I tried the below options, but none of them is suitable as a health check.

netstat -an | grep 9083 | grep LISTEN | echo $?  # This works
netstat -an | grep 9084 | grep LISTEN | echo $? # but so does this

The problem as I interpret from the above is it's simply telling me my syntax is correct, but not really testing if that port is really listening

because when I do netstat -an I get the following output,which clearly shows only 9083 is listening but not 9084

Active Internet connections (servers and established) Proto Recv-Q Send-Q Local  Address           Foreign Address         State tcp       0      0 
 0.0.0.0:9083            0.0.0.0:*               LISTEN tcp    0      0 

Upvotes: 15

Views: 24047

Answers (6)

ealfonso
ealfonso

Reputation: 7312

You don't need nc, netstat etc, you can simply use bash:

service:
    build: ./service
    ...
    healthcheck:
      test: bash -c "exec 6<> /dev/tcp/localhost/80"

Upvotes: 6

aldraia
aldraia

Reputation: 81

I really loved Wassim Dhif answer. Mostly because it does not depend on netstat. Netstat was obsolete before the question was asked.

From netstat's manpage:

Note
This program is obsolete. Replacement for netstat is ss. Replacement for netstat -r is ip route. Replacement for netstat -i is ip -s link. Replacement for netstat -g is ip maddr.

And you need netstat (or ss) installed in the container. You only want to check if a port is open. Wassim Dhif's answer just needs bash (and yes, not every image has it). In my experience, you usually want the image as light as possible.

In my compose I used it as follows:

healthcheck:
  test: "bash -c 'printf \"GET / HTTP/1.1\n\n\" > /dev/tcp/127.0.0.1/8080; exit $?;'"
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 30s

Note that the string test is equivalent to specifying CMD-SHELL followed by that string (from the Compose Specification

Upvotes: 2

rudihaus
rudihaus

Reputation: 53

Piotr Perzynas answer is quite good, but it will also return 0 if there‘s a port like 19083 because it finds the substring 9083 in that line. a better check would be:

netstat -ltn | grep -c ":9083"

Upvotes: 3

Piotr Perzyna
Piotr Perzyna

Reputation: 139

The shorter version of it:

netstat -ltn | grep -c 9083

Used options:

netstat:

  • -l - display listening server sockets
  • -t - display TCP sockets only
  • -n - don't resolve names

grep

  • -c - returns a number of founded lines, but it also gives a useful exit code; 0 if found, 1 if not found

Upvotes: 12

Alfiyum
Alfiyum

Reputation: 411

Though answering an old question, for future googlers, the following worked for me:

HEALTHCHECK CMD netstat -an | grep 9083 > /dev/null; if [ 0 != $? ]; then exit 1; fi;

Upvotes: 19

Wassim Dhif
Wassim Dhif

Reputation: 1378

You can use /dev/tcp

Like this :

printf "GET / HTTP/1.1\n\n" > /dev/tcp/127.0.0.1/9083

For more information, you can check this : http://www.tldp.org/LDP/abs/html/devref1.html#DEVTCP

Upvotes: 13

Related Questions