0

My goal is to have a HEALTHCHECK command in my Dockerfile to check if the webserver is working alright by simply making a request to the website and check if it receives a "proper response".

The problem I'm having is that the application has an authentication middleware, which causes the application to return an error (401 Unauthorized), causing CURL to fail and return curl: (7) Failed to connect to host.docker.internal port 8000: Connection refused.

If I remove the authentication middleware it doesn't return anything, which is what I'm aiming for.

The command I'm using is the following (I'm currently just using it inside a container, trying to find a solution):

curl --fail http://host.docker.internal:8000

I know I can tell CURL the username and password but that's something I would rather not do it.

Having a way to tell CURL that Unauthorized (error 401) is fine or to consider a connection refused error (curl: (7)) as the only error would be fine but it would be even better if I could decide what should CURL consider and/or not consider a success. Is there any way to do something like this with one or more CURL options?

Pedro Rodrigues
  • 637
  • 6
  • 16
  • 1
    the standard response for a successful HTTP request is `200 - OK` - the `--fail` only hides the failure. It does not mean the request was successful. The standard HTTP responses are what curl would also return - see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status – blurfus Aug 17 '21 at 17:10
  • @blurfus I know but in my case the application asks for authentication, which means it returns 401 if I don't give the username and password. Since my aim is to only know if the webserver is up and running as it should, I'm ok with a 401 error (since it's what it should return in this situation). – Pedro Rodrigues Aug 17 '21 at 17:14
  • but the 401 does not come from your server, it comes from the middleware so I am not sure how you can tell if the server/service is OK by getting a 401 from the middleware – blurfus Aug 17 '21 at 17:16
  • 1
    This might help you but you need to understand that a response from the middleware is not necessarily a response from the end service: https://superuser.com/questions/854101/whats-the-exit-code-for-curl-i-when-not-http-200 – blurfus Aug 17 '21 at 17:16
  • @blurfus I have a container that is in charge of the webserver and another one that is in charge of PHP. I'm using CURL inside the PHP container to connect with the service that the other container is making available. If I can't get a response from it then it means that something is wrong with that container/the web service (since Laravel's middleware will only do something if it doesn't fail at that point). Am I wrong? – Pedro Rodrigues Aug 17 '21 at 17:37
  • #1 health check must respect standard codes 20x = success , any other code = error. #2 What language are using in your dockerfile? #3 Are you open to an alternative of curl for your health check? – JRichardsz Aug 17 '21 at 17:38
  • @JRichardsz Yes, I'm open to an alternative, I'm using CURL because I thought it was a good solution (and because it's the example that is in Docker's documentation). By reading the documentation I thought Healthcheck was only dependant on the exit code of the used command (being 0, 1 or 2)? If that's not the case then I should go read more about it... – Pedro Rodrigues Aug 17 '21 at 17:43
  • @JRichardsz And about the language in Dockerfile, I just used bash/shell script till now – Pedro Rodrigues Aug 17 '21 at 18:01

1 Answers1

3

Health check is a good practice when microservices or rest services architecture are used.

Default health endpoints and check platforms needs 200 as http code to flag your app as healthy. Any other response is flagged ad unhealthy.

Custom codes with curl

I tried and I can say: with curl is not possible:

You need a custom logic.

Custom health

As you are using ubuntu based image, you could use a simple bash function to catch 401 codes and return exit 0 in order to mark as healthy your container.

with curl

The cornerstone here is the option to retrieve just the response code from curl invokation:

curl -o /dev/null -s -w "%{http_code}\n" http://localhost

So you can create a bash script to execute your curl invocation and return:

  • exit 0 just for 200 & 401
  • And exit 1 in any other case .
#healthcheck.sh
code=$(curl -o /dev/null -s -w "%{http_code}\n" http://localhost:12345)

echo "response code:$code"
if [ "$code" == "200" ] || [ "$code" == "401" ]
then
  echo "success"
  exit 0;
else
  echo "error"
  exit 1;
fi

Finally you can use this script in your healthcheck in any language(php in your case):

FROM node
COPY server.js /
HEALTHCHECK --interval=5s --timeout=10s --retries=3 CMD curl -sS 127.0.0.1:8080 || exit 1
CMD [ "node", "/server.js" ]

Health feature should be public

Common health verification is related to: server status, internet connection, ram, disk, database connectivity, and any other stat that indicates you if you app is running and is ok.

Health check platforms does not allow us to register complex security flows (oauth1, ouath2, openid, etc). Just allow us to register a simple http endpoint. Here an example from aws ELB check configuration

aws-elb-health-check

Health feature should not expose any other sensitive data, because of that, this endpoint could be public. Classic and public webpages, web systems or public apis are examples.

Workaround

In some strict cases, privacy is required.

  1. In this case I protected the /health with a simple apikey value as query parameter. In the controller, I validate if it is equal to some value. Final health endpoint will be /health?apiKey=secret and this is easy to register in check platforms.
  2. Using complex configurations you could allow /health just for internal private lan, not for public access. So in this case your /health is secure
JRichardsz
  • 14,356
  • 6
  • 59
  • 94
  • Thanks a lot for the answer, it was very clear :) Regarding "healthcheck", I don't think we are exactly talking about the same functionality. I was talking about a specific Docker instruction: https://docs.docker.com/engine/reference/builder/#healthcheck. Nevertheless, it was a good reading and interesting. – Pedro Rodrigues Aug 17 '21 at 18:58
  • I know that you are talking about docker :). I didn't add it to the answer because your question is about curl. You can apply one of the explained strategies like **Custom health** to your docker healthcheck. I will update the answer – JRichardsz Aug 17 '21 at 20:38