diff --git a/tools/docker/healthcheck.sh b/tools/docker/healthcheck.sh index 493a641c57b1..6652177f0543 100755 --- a/tools/docker/healthcheck.sh +++ b/tools/docker/healthcheck.sh @@ -1,18 +1,33 @@ #!/bin/sh +# Cleanup function to prevent zombie processes (issue #5844) +# This is critical when dragonfly runs as PID 1 without an init system +cleanup() { + # Wait for all background/child processes to finish + wait 2>/dev/null || true +} + +# Set trap to ensure cleanup runs on exit, regardless of how the script exits +trap cleanup EXIT + +# Parse command line arguments +CHECK_LOADING=false +if [ "$1" = "--check-loading" ] || [ "$1" = "-l" ]; then + CHECK_LOADING=true +fi + HOST="localhost" PORT=$HEALTHCHECK_PORT - if [ -z "$HEALTHCHECK_PORT" ]; then # try unpriveleged version first. This should cover cases when the container is running # without root, for example: # docker run --group-add 999 --cap-drop=ALL --user 999 docker.dragonflydb.io/dragonflydb/dragonfly - DF_NET=$(netstat -tlnp | grep "1/dragonfly") + DF_NET=$(netstat -tlnp | grep "/dragonfly") if [ -z "$DF_NET" ]; then # if we failed, then lets try the priveleged version. is triggerred by the regular command: # docker run docker.dragonflydb.io/dragonflydb/dragonfly - DF_NET=$(su dfly -c "netstat -tlnp" | grep "1/dragonfly") + DF_NET=$(su dfly -c "netstat -tlnp" | grep "/dragonfly") fi # check all the TCP ports, and fetch the port. @@ -22,6 +37,22 @@ fi _healthcheck="nc -q1 $HOST $PORT" -echo PING | ${_healthcheck} +# Send PING and check response +RESPONSE=$(echo PING | timeout 3 ${_healthcheck} 2>/dev/null) -exit $? +# Check response +if echo "$RESPONSE" | grep -q "PONG"; then + # Server responded with PONG - it's running + exit 0 +elif echo "$RESPONSE" | grep -qi "LOADING"; then + # Server is loading dataset + # Only fail if --check-loading flag is set + if [ "$CHECK_LOADING" = true ]; then + exit 1 # Not ready for traffic + else + exit 0 # Backward compatible: accept LOADING as healthy + fi +else + # Unknown response or connection failed + exit 1 +fi diff --git a/tools/packaging/Dockerfile.alpine-dev b/tools/packaging/Dockerfile.alpine-dev index 07ecba059228..200a5c4ca695 100644 --- a/tools/packaging/Dockerfile.alpine-dev +++ b/tools/packaging/Dockerfile.alpine-dev @@ -35,7 +35,7 @@ COPY tools/docker/healthcheck.sh /usr/local/bin/healthcheck.sh COPY --from=builder /build/build-release/dragonfly /usr/local/bin/ RUN apk --no-cache add libgcc libstdc++ \ - setpriv netcat-openbsd boost-context && ldd /usr/local/bin/dragonfly + setpriv netcat-openbsd boost-context tini && ldd /usr/local/bin/dragonfly RUN addgroup -S -g 1000 dfly && adduser -S -G dfly -u 999 dfly RUN mkdir /data && chown dfly:dfly /data @@ -44,7 +44,9 @@ VOLUME /data WORKDIR /data HEALTHCHECK CMD /usr/local/bin/healthcheck.sh -ENTRYPOINT ["entrypoint.sh"] + +# Use tini as PID 1 to properly reap zombie processes (issue #5844) +ENTRYPOINT ["/sbin/tini", "--", "entrypoint.sh"] EXPOSE 6379 diff --git a/tools/packaging/Dockerfile.ubuntu-dev b/tools/packaging/Dockerfile.ubuntu-dev index 4c8ad1323374..d368ec79a67d 100644 --- a/tools/packaging/Dockerfile.ubuntu-dev +++ b/tools/packaging/Dockerfile.ubuntu-dev @@ -19,7 +19,7 @@ FROM ubuntu:22.04 RUN --mount=type=tmpfs,target=/var/cache/apt \ --mount=type=tmpfs,target=/var/lib/apt/lists \ apt update && \ - apt install -q -y --no-install-recommends netcat-openbsd ca-certificates redis-tools net-tools + apt install -q -y --no-install-recommends netcat-openbsd ca-certificates redis-tools net-tools tini RUN groupadd -r -g 999 dfly && useradd -r -g dfly -u 999 dfly RUN mkdir /data && chown dfly:dfly /data @@ -32,7 +32,9 @@ COPY tools/docker/healthcheck.sh /usr/local/bin/healthcheck.sh COPY --from=builder /build/build-release/dragonfly /usr/local/bin/ HEALTHCHECK CMD /usr/local/bin/healthcheck.sh -ENTRYPOINT ["entrypoint.sh"] + +# Use tini as PID 1 to properly reap zombie processes (issue #5844) +ENTRYPOINT ["/usr/bin/tini", "--", "entrypoint.sh"] # For inter-container communication. EXPOSE 6379 diff --git a/tools/packaging/Dockerfile.ubuntu-prod b/tools/packaging/Dockerfile.ubuntu-prod index 97d5fb661238..fb4ec478f5d1 100644 --- a/tools/packaging/Dockerfile.ubuntu-prod +++ b/tools/packaging/Dockerfile.ubuntu-prod @@ -20,7 +20,7 @@ ARG DEBIAN_FRONTEND=noninteractive RUN --mount=type=tmpfs,target=/var/cache/apt \ --mount=type=tmpfs,target=/var/lib/apt/lists \ apt -q update && \ - apt install -q -y --no-install-recommends netcat-openbsd ca-certificates redis-tools net-tools + apt install -q -y --no-install-recommends netcat-openbsd ca-certificates redis-tools net-tools tini RUN groupadd -r -g 999 dfly && useradd -r -g dfly -u 999 dfly RUN mkdir /data && chown dfly:dfly /data @@ -33,7 +33,9 @@ COPY tools/docker/healthcheck.sh /usr/local/bin/healthcheck.sh COPY --from=builder /build/dragonfly /usr/local/bin/ HEALTHCHECK CMD /usr/local/bin/healthcheck.sh -ENTRYPOINT ["entrypoint.sh"] + +# Use tini as PID 1 to properly reap zombie processes (issue #5844) +ENTRYPOINT ["/usr/bin/tini", "--", "entrypoint.sh"] # For inter-container communication. EXPOSE 6379