bin/docker-compose
Rama master · réplica de lectura del repositorio original.
#!/bin/sh
set -eu
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd -P)
cd "$SCRIPT_DIR/.."
env_override=${ENV_OVERRIDE:-./.env.override}
cloud_dir=${CLOUD_DIR:-../cloud}
SHELLHUB_EDITION=$(
. ./.env 2>/dev/null
[ -f "$env_override" ] && . "$env_override"
eval "printf '%s' \"\${SHELLHUB_EDITION:-community}\""
)
SHELLHUB_EDITION=$(printf '%s' "$SHELLHUB_EDITION" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')
case "$SHELLHUB_EDITION" in
community|enterprise|cloud) ;;
*)
echo "🚫 ERROR: invalid SHELLHUB_EDITION '$SHELLHUB_EDITION': must be community, enterprise, or cloud." >&2
exit 1
;;
esac
env_var() {
var=$1; default=$2
edition=$SHELLHUB_EDITION
(
. ./.env 2>/dev/null
[ "$edition" != "community" ] && [ -f "$cloud_dir/.env" ] \
&& . "$cloud_dir/.env"
[ -f "$env_override" ] && . "$env_override"
eval "printf '%s' \"\${${var}:-${default}}\""
)
}
SHELLHUB_ENV=$(env_var SHELLHUB_ENV production)
SHELLHUB_AUTO_SSL=$(env_var SHELLHUB_AUTO_SSL false)
SHELLHUB_DATABASE=$(env_var SHELLHUB_DATABASE postgres)
SHELLHUB_POSTGRES_EXTERNAL=$(env_var SHELLHUB_POSTGRES_EXTERNAL false)
SHELLHUB_BILLING=$(env_var SHELLHUB_BILLING "")
EXTRA_COMPOSE_FILE=${EXTRA_COMPOSE_FILE:-$(env_var EXTRA_COMPOSE_FILE "")}
sbin_path="$PATH:/usr/sbin:/sbin"
daemon_is_rootless() {
docker info --format '{{.SecurityOptions}}' 2>/dev/null | grep -q 'name=rootless'
}
daemon_socket() {
docker_host=${DOCKER_HOST:-$(docker context inspect --format '{{.Endpoints.docker.Host}}' 2>/dev/null || true)}
case "$docker_host" in
unix://*) echo "${docker_host#unix://}" ;;
esac
}
rootlesskit_capabilities() {
rootlesskit=${ROOTLESSKIT-$(command -v rootlesskit 2>/dev/null)}
[ -n "$rootlesskit" ] || return 127
PATH="$sbin_path" getcap "$rootlesskit" 2>/dev/null
}
lowest_published_port() {
docker compose config 2>/dev/null \
| sed -n 's/^ *published: "\{0,1\}\([0-9][0-9]*\)"\{0,1\}$/\1/p' \
| sort -n | head -n 1
}
rootless=false
if [ "$SHELLHUB_ENV" = "development" ] && daemon_is_rootless; then
rootless=true
socket=$(daemon_socket)
[ -z "$socket" ] || export SHELLHUB_DEV_DOCKER_SOCKET="$socket"
fi
COMPOSE_ENV_FILES="./.env,./versions.env"
[ "$SHELLHUB_EDITION" != "community" ] && [ -f ./.env.enterprise ] \
&& COMPOSE_ENV_FILES="$COMPOSE_ENV_FILES,./.env.enterprise"
[ "$SHELLHUB_EDITION" != "community" ] && [ -f "$cloud_dir/.env" ] \
&& COMPOSE_ENV_FILES="$COMPOSE_ENV_FILES,$cloud_dir/.env"
[ -f "$env_override" ] && COMPOSE_ENV_FILES="$COMPOSE_ENV_FILES,$env_override"
export COMPOSE_ENV_FILES
COMPOSE_FILE="docker-compose.yml"
[ "$SHELLHUB_AUTO_SSL" = "true" ] && COMPOSE_FILE="${COMPOSE_FILE}:docker-compose.autossl.yml"
[ "$SHELLHUB_ENV" = "development" ] && COMPOSE_FILE="${COMPOSE_FILE}:docker-compose.dev.yml:docker-compose.agent.yml"
[ "$SHELLHUB_EDITION" != "community" ] && [ "$SHELLHUB_ENV" != "development" ] && COMPOSE_FILE="${COMPOSE_FILE}:docker-compose.enterprise.yml"
[ "$SHELLHUB_EDITION" != "community" ] && [ "$SHELLHUB_ENV" = "development" ] && [ -f "$cloud_dir/docker-compose.enterprise.dev.yml" ] && COMPOSE_FILE="${COMPOSE_FILE}:$cloud_dir/docker-compose.enterprise.dev.yml"
[ "$SHELLHUB_EDITION" = "cloud" ] && [ -f "$cloud_dir/docker-compose.yml" ] && COMPOSE_FILE="${COMPOSE_FILE}:$cloud_dir/docker-compose.yml"
[ -n "$SHELLHUB_BILLING" ] && export COMPOSE_PROFILES="$SHELLHUB_BILLING"
[ "$SHELLHUB_DATABASE" = "postgres" ] \
|| echo "⚠️ WARNING: Unknown SHELLHUB_DATABASE '$SHELLHUB_DATABASE'. Defaulting to postgres." >&2
[ "$SHELLHUB_POSTGRES_EXTERNAL" = "true" ] || COMPOSE_FILE="${COMPOSE_FILE}:docker-compose.postgres.yml"
[ -f docker-compose.override.yml ] && COMPOSE_FILE="${COMPOSE_FILE}:docker-compose.override.yml"
if [ -n "$EXTRA_COMPOSE_FILE" ]; then
if [ ! -f "$EXTRA_COMPOSE_FILE" ]; then
echo "🚫 ERROR: EXTRA_COMPOSE_FILE '$EXTRA_COMPOSE_FILE' does not exist." >&2
exit 1
fi
COMPOSE_FILE="${COMPOSE_FILE}:${EXTRA_COMPOSE_FILE}"
fi
export COMPOSE_FILE
installed_playwright_version() {
sed -n '/"node_modules\/@playwright\/test": {/{n;s/.*"version": "\([^"]*\)".*/\1/p;}' ui/package-lock.json 2>/dev/null
}
export SHELLHUB_WORKSPACE="${SHELLHUB_WORKSPACE:-$(cd .. && pwd -P)}"
export E2E_PLAYWRIGHT_VERSION="${E2E_PLAYWRIGHT_VERSION:-$(installed_playwright_version)}"
if [ "$rootless" = true ]; then
port=$(lowest_published_port)
unprivileged_start=$(PATH="$sbin_path" sysctl -n net.ipv4.ip_unprivileged_port_start 2>/dev/null || echo 1024)
if [ -n "$port" ] && [ "$port" -lt "$unprivileged_start" ]; then
capabilities=$(rootlesskit_capabilities) && getcap_status=0 || getcap_status=$?
if [ "$getcap_status" -eq 127 ]; then
echo "⚠️ WARNING: getcap or rootlesskit not found, cannot tell whether rootless Docker may publish port $port." >&2
elif ! echo "$capabilities" | grep -q 'cap_net_bind_service'; then
echo "🚫 ERROR: rootless Docker cannot publish port $port. Either grant rootlesskit the capability:" >&2
echo " sudo setcap cap_net_bind_service=ep \"\$(command -v rootlesskit)\" && systemctl --user restart docker" >&2
echo " or set SHELLHUB_HTTP_PORT, SHELLHUB_HTTPS_PORT and SHELLHUB_SSH_PORT to $unprivileged_start or above in .env.override." >&2
exit 1
fi
fi
fi
exec docker compose "$@"