mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-21 16:18:55 +00:00
fix(docker): strip tini -g flags in legacy entrypoint shim
A plain /usr/bin/tini → /init symlink forwarded tini's -g into s6-overlay's rc.init as the container CMD, causing boot loops after image updates that preserve old entrypoints (#66679).
This commit is contained in:
parent
3d9be27895
commit
be3c160a85
2 changed files with 102 additions and 11 deletions
24
Dockerfile
24
Dockerfile
|
|
@ -73,17 +73,19 @@ RUN set -eu; \
|
|||
tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz; \
|
||||
tar -C / -Jxpf /tmp/s6-overlay-arch.tar.xz; \
|
||||
tar -C / -Jxpf /tmp/s6-overlay-symlinks-noarch.tar.xz; \
|
||||
rm /tmp/s6-overlay-*.tar.xz /tmp/s6-overlay.sha256; \
|
||||
# #34192: backward-compat shim for orchestration templates that still\
|
||||
# reference the legacy /usr/bin/tini entrypoint (e.g. Hostinger's\
|
||||
# 'Hermes WebUI' catalog). The image has moved to s6-overlay /init\
|
||||
# as PID 1 (see ENTRYPOINT below + the migration comment at the top\
|
||||
# of this file), but external wrappers pinned to /usr/bin/tini will\
|
||||
# crash with 'tini: No such file or directory' on startup. The shim\
|
||||
# symlinks /usr/bin/tini -> /init so legacy wrappers exec the right\
|
||||
# PID-1 reaper without behavior change for users on the current\
|
||||
# ENTRYPOINT. Safe to drop once the affected catalogs are updated.\
|
||||
ln -sf /init /usr/bin/tini
|
||||
rm /tmp/s6-overlay-*.tar.xz /tmp/s6-overlay.sha256
|
||||
|
||||
# #34192 / #66679: backward-compat shim for orchestration templates that
|
||||
# still reference the legacy /usr/bin/tini entrypoint (Hostinger's
|
||||
# 'Hermes WebUI' catalog, NAS compose projects that preserve an old
|
||||
# entrypoint on image update, etc.). A plain symlink to /init made the
|
||||
# path exist, but forwarded tini flags like `-g` into s6-overlay's
|
||||
# rc.init as the container CMD (`rc.init: 91: -g: not found`) and
|
||||
# boot-looped any `restart: unless-stopped` deploy. The shim strips the
|
||||
# tini CLI surface, then exec's /init + main-wrapper — see
|
||||
# docker/tini-shim.sh. Safe to drop once the affected catalogs are
|
||||
# updated.
|
||||
COPY --chmod=0755 docker/tini-shim.sh /usr/bin/tini
|
||||
|
||||
# Non-root user for runtime; UID can be overridden via HERMES_UID at runtime
|
||||
RUN useradd -u 10000 -m -d /opt/data hermes
|
||||
|
|
|
|||
89
docker/tini-shim.sh
Executable file
89
docker/tini-shim.sh
Executable file
|
|
@ -0,0 +1,89 @@
|
|||
#!/bin/sh
|
||||
# shellcheck shell=sh
|
||||
# /usr/bin/tini — compatibility shim for legacy orchestration templates.
|
||||
#
|
||||
# Background
|
||||
# ----------
|
||||
# The published image used to ship real `tini` as PID 1. After the
|
||||
# s6-overlay migration, PID 1 is `/init`. Downstream catalogs (Hostinger
|
||||
# Hermes WebUI, NAS "update" flows that preserve an old entrypoint, etc.)
|
||||
# still pin entrypoints like:
|
||||
#
|
||||
# ["/usr/bin/tini", "-g", "--"]
|
||||
# ["/usr/bin/tini", "-g", "--", "gateway", "run"]
|
||||
#
|
||||
# A plain `ln -sf /init /usr/bin/tini` (#34192) made the binary exist, but
|
||||
# forwarded tini's own flags into s6-overlay. `/init` then handed `-g` to
|
||||
# `rc.init` as the container CMD, which fails with:
|
||||
#
|
||||
# /run/s6/basedir/scripts/rc.init: 91: -g: not found
|
||||
#
|
||||
# …and with `restart: unless-stopped` the container boot-loops forever
|
||||
# (#66679).
|
||||
#
|
||||
# This shim strips the tini CLI surface, then exec's `/init` with the
|
||||
# image's main-wrapper so privilege drop + arg routing still apply.
|
||||
#
|
||||
# Tini flags we discard (see krallin/tini --help):
|
||||
# -g / --kill-process-group, -s / --subreaper, -w, -v (repeatable),
|
||||
# -h / --help, -l, --version, -p SIGNAL, -e EXIT_CODE, and `--`.
|
||||
# s6-overlay already reaps zombies and forwards signals as PID 1; the
|
||||
# flag semantics are intentionally no-ops here.
|
||||
#
|
||||
# Test hook: HERMES_TINI_SHIM_TARGET overrides the `/init` path (and
|
||||
# HERMES_TINI_SHIM_WRAPPER the main-wrapper path) so unit tests can
|
||||
# record argv without a real s6 tree.
|
||||
|
||||
set -e
|
||||
|
||||
INIT_TARGET="${HERMES_TINI_SHIM_TARGET:-/init}"
|
||||
WRAPPER="${HERMES_TINI_SHIM_WRAPPER:-/opt/hermes/docker/main-wrapper.sh}"
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-g|--kill-process-group|-s|--subreaper|-w|-l|-h|--help|--version)
|
||||
shift
|
||||
;;
|
||||
-v)
|
||||
# tini allows repeated -v; drop them all.
|
||||
shift
|
||||
;;
|
||||
-p|-e)
|
||||
# These take a mandatory argument.
|
||||
shift
|
||||
if [ "$#" -gt 0 ]; then
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
-*)
|
||||
# Unknown short/long option from an older/newer tini — drop
|
||||
# rather than forwarding into /init (would recreate #66679).
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# No program left (entrypoint was just `tini -g --`) → same as the
|
||||
# image's default ENTRYPOINT + empty CMD.
|
||||
if [ "$#" -eq 0 ]; then
|
||||
exec "$INIT_TARGET" "$WRAPPER"
|
||||
fi
|
||||
|
||||
# Caller already supplied the wrapper or /init — don't double-wrap.
|
||||
case "$1" in
|
||||
/init|"$INIT_TARGET")
|
||||
exec "$@"
|
||||
;;
|
||||
"$WRAPPER"|*/main-wrapper.sh)
|
||||
exec "$INIT_TARGET" "$@"
|
||||
;;
|
||||
esac
|
||||
|
||||
exec "$INIT_TARGET" "$WRAPPER" "$@"
|
||||
Loading…
Add table
Add a link
Reference in a new issue