#!/bin/sh # shellcheck shell=sh # /opt/hermes/docker/main-wrapper.sh — wraps the container's CMD with # the same argument-routing logic the pre-s6 entrypoint.sh used. Runs # as /init's "main program" (Docker CMD) so it inherits stdin/stdout/ # stderr from the container. The non-PID-1 entrypoint fallback also # execs this script directly after running the stage2 bootstrap. # # Env note: /init scrubs env before invoking CMD, so when this wrapper # is launched through the supervised path it must rehydrate via # with-contenv before touching HERMES_HOME / PATH. On the non-PID-1 # fallback path the Dockerfile env is still intact, so we skip the # re-exec and continue directly. # # Routing: # no args → exec `hermes` (the default) # first arg is an executable → exec it directly (sleep, bash, sh, …) # first arg is anything else → exec `hermes ` (subcommand passthrough) # # Drop to hermes via s6-setuidgid, but skip it when already non-root. set -e if [ -z "${HERMES_MAIN_WRAPPER_ENV_READY:-}" ] && \ [ -z "${HERMES_HOME:-}" ] && \ [ -x /command/with-contenv ]; then export HERMES_MAIN_WRAPPER_ENV_READY=1 exec /command/with-contenv sh "$0" "$@" fi unset HERMES_MAIN_WRAPPER_ENV_READY drop() { [ "$(id -u)" = 0 ] && set -- s6-setuidgid hermes "$@"; exec "$@"; } # --- Reject the unsupported `docker run --user :` start --- # Mirror the guard in stage2-hook.sh (cont-init). This is the surface the # user actually sees in `docker run` output: when the container is pinned to # an arbitrary non-root, non-hermes UID, the bootstrap was skipped and the # baked image dirs (owned by the hermes build UID) are unwritable, so fail # fast here with actionable guidance rather than crashing on `cd`/EACCES # further down. See stage2-hook.sh for the full rationale. cur_uid="$(id -u)" if [ "$cur_uid" != 0 ] && [ "$cur_uid" != "$(id -u hermes)" ]; then cat >&2 </dev/null 2>&1; then # Bare executable — pass through directly. drop "$@" fi # Hermes subcommand pass-through. drop hermes "$@"