From 7c645cf3801cf1541c2604a23d4eb5182e27bb9d Mon Sep 17 00:00:00 2001 From: QianEric <307361214+qianeric-backup@users.noreply.github.com> Date: Thu, 29 Oct 2026 22:54:12 +0800 Subject: [PATCH] fix(docker): resolve the healthcheck port instead of passing a literal The healthcheck was declared in JSON exec form: CMD [ "curl", "-fS", "localhost:$UI_PORT" ] Exec-form healthchecks do not run through a shell, and Docker does not interpolate variables inside an argv element, so the image stored the literal string "localhost:$UI_PORT" and curl rejected it before opening a connection: curl: (3) URL rejected: Port number was not a decimal number between 0 and 65535 The container therefore never reported healthy, even with BeEF listening on the default port. Two changes are needed, because either one alone is insufficient: - UI_PORT and the sibling ports are now also exported as environment variables. A build argument is not visible at run time, so a shell-form healthcheck would otherwise expand ${UI_PORT} to an empty string. - The healthcheck uses the shell form so that expansion happens when the check runs, plus an explicit `|| exit 1` to keep curl's status as the healthcheck status. Verified with a listener on port 3000: the old command exits 3, the new one returns the response and exits 0. Note this keeps the existing relationship between the build arguments and the application: BeEF reads its listen address from config.yaml, so a non-default UI_PORT still only affects the image metadata and this check. Aligning the two would be a separate change. Refs #3626 --- Dockerfile | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c8c02a011b..8da18485e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,6 +58,13 @@ ARG PROXY_PORT=6789 ARG WEBSOCKET_PORT=61985 ARG WEBSOCKET_SECURE_PORT=61986 +# Promote the port arguments to environment variables. Build arguments are not +# visible once the image runs, and exec-form healthchecks never expand +# variables, so the healthcheck below needs a run-time resolvable value. +ENV UI_PORT=${UI_PORT} \ + PROXY_PORT=${PROXY_PORT} \ + WEBSOCKET_PORT=${WEBSOCKET_PORT} \ + WEBSOCKET_SECURE_PORT=${WEBSOCKET_SECURE_PORT} # Create service account to run BeEF and install BeEF's runtime dependencies RUN adduser --home /beef --gecos beef --disabled-password beef \ @@ -102,7 +109,11 @@ USER beef # Expose UI, Proxy, WebSocket server, and WebSocketSecure server ports EXPOSE $UI_PORT $PROXY_PORT $WEBSOCKET_PORT $WEBSOCKET_SECURE_PORT -HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD [ "curl", "-fS", "localhost:$UI_PORT" ] +# The shell form is required here: Docker stores exec-form argv verbatim and +# does not interpolate variables inside an argument, so the healthcheck would +# request a port literally named "$UI_PORT" and always report unhealthy. +HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \ + CMD curl -fS "http://localhost:${UI_PORT}" || exit 1 WORKDIR /beef ENTRYPOINT ["/beef/beef"]