dart-lang / dart-docker

Docker images for the Dart programming language (https://dart.dev)
BSD 3-Clause "New" or "Revised" License
67 stars 15 forks source link

How to execute healthcheck without curl #58

Closed PlugFox closed 2 years ago

PlugFox commented 2 years ago

How to perform healthcheck shelf service without curl in docker swarm stack?

Should i use curlimages/curl instead scratch? Or maybe run dart runtime with flag and check working instance with http request?

PlugFox commented 2 years ago

My current solution

dockerfile:

FROM dart:beta AS build

WORKDIR /app

COPY ./shared /app/shared
COPY ./server /app/server

# Ensure packages are still up-to-date if anything has changed
RUN cd server && dart pub get \
   #&& dart pub run build_runner build --delete-conflicting-outputs \
    && dart compile exe bin/job.dart -o bin/server

# Build minimal serving image from AOT-compiled `/server` and required system
# libraries and configuration files stored in `/runtime/` from the build stage.
#FROM scratch
FROM curlimages/curl AS production

COPY --from=build /runtime/ /
COPY --from=build /app/server/bin/server /app/bin/

LABEL name="" \
      vcs-url="" \
      maintainer="" \
      authors="" \
      family=""

ENV PORT=80
EXPOSE 80/tcp

ENTRYPOINT ["/app/bin/server", "--port=80"]

healthcheck:

    healthcheck:
      test: curl --fail -s http://127.0.0.1:80/health || exit 1
      interval: 15s
      timeout: 10s
      retries: 3
athomas commented 2 years ago

@kevmoo Is this something we want to document? We currently just document how to get a minimal container. Adding curl by default is probably not what we want (you might not perform the healthcheck from within the container, use the container for CLI tool rather than a server, write your own fancy healthcheck in Dart, etc...). This is also not very Dart specific, it applies to FROM scratch containers in general.

Otherwise I'm inclined to close as won't fix.

kevmoo commented 2 years ago

Agree, @athomas – maybe @subfuzion has thoughts here

athomas commented 2 years ago

Ok, I'm going to close this for now (seems more like a stack overflow question). @subfuzion please re-open if you disagree.

PlugFox commented 2 years ago

I have an idea of how to do simple health checks without curl:

With that command:

    healthcheck:
      #test: curl --fail -s http://127.0.0.1:80/healthcheck || exit 1
      test: timeout 10s bash -c ':> /dev/tcp/127.0.0.1/80' || exit 1
      interval: 30s
      timeout: 15s
      retries: 3

Inspired of that article

ivan-kleshnin commented 2 years ago

Inspired of that article

Cool idea but impractical. Not working with usual Bash without net-redirections -> you have to install a new Bash -> you'd rather install Curl.

DoenertellerVersace commented 1 year ago

this script actually does it for me, works with usual bash:

#!/bin/bash

exec 3<>/dev/tcp/localhost/"$1"

echo -e "GET /path/to/health/endpoint/ HTTP/1.1
host: localhost:$1
" >&3

timeout 1 cat <&3 | grep status | grep UP || exit 1

of course you will have to alter the path to your health endpoint as well as the grep s to whatever you are looking for in a healthy status answer.

the way it works is by using this sentence to your advantage:

image

so by exec 3<>/dev/tcp/localhost/"$1" i am redirecting FD 3 to the specified port for the current shell.

more on this here: https://ceh51.blogspot.com/2016/07/how-to-open-tcpudp-sockets-bash-shell.html

you can use the script in your compose.yaml like so:

    healthcheck:
      test: [ 'CMD-SHELL', '/bin/bash -c "/path/to/healthcheck.sh 8081"' ]
      ...
TimChaubet-I4U commented 1 year ago

For nodejs containers:

healthcheck:  echo 'var http = require("http"); var options = { host : "localhost", port : "3000", timeout : 2000 }; var request = http.request(options, (res) => { console.log(`STATUS: ${res.statusCode}`
); if (res.statusCode == 200) {  process.exit(0); } else { process.exit(1); } }); request.on("error", function(err) { console.log('ERROR'); process.exit(1); }); request.end();' > /healthcheck.js && node /healthcheck.js

reference: https://blog.sixeyed.com/docker-healthchecks-why-not-to-use-curl-or-iwr/