Files
dockhand/docker-entrypoint-node.sh
2026-04-26 08:01:32 +02:00

194 lines
7.2 KiB
Bash

#!/bin/sh
set -e
# Dockhand Docker Entrypoint (Node.js)
# === Configuration ===
PUID=${PUID:-1001}
PGID=${PGID:-1001}
# Increase body size limit for container file uploads (default 512KB is too small)
export BODY_SIZE_LIMIT=${BODY_SIZE_LIMIT:-2G}
# Default command (--expose-gc allows forced GC from /api/debug/memory?gc=true)
# Custom CA: set NODE_EXTRA_CA_CERTS=/path/to/ca.crt (appends to built-in CAs, git ops auto-merge with system CAs)
# Enterprise (system CA store): set NODE_OPTIONS="--use-openssl-ca"
if [ "$MEMORY_MONITOR" = "true" ]; then
DEFAULT_CMD="node --dns-result-order=ipv4first --no-network-family-autoselection --expose-gc /app/server.js"
else
DEFAULT_CMD="node --dns-result-order=ipv4first --no-network-family-autoselection /app/server.js"
fi
# === Detect if running as root ===
RUNNING_AS_ROOT=false
if [ "$(id -u)" = "0" ]; then
RUNNING_AS_ROOT=true
fi
# === Non-root mode (user: directive in compose) ===
if [ "$RUNNING_AS_ROOT" = "false" ]; then
echo "Running as user $(id -u):$(id -g) (set via container user directive)"
DATA_DIR="${DATA_DIR:-/app/data}"
if [ ! -d "$DATA_DIR/db" ]; then
echo "Creating database directory at $DATA_DIR/db"
mkdir -p "$DATA_DIR/db" 2>/dev/null || {
echo "ERROR: Cannot create $DATA_DIR/db directory"
echo "Ensure the data volume is mounted with correct permissions for user $(id -u):$(id -g)"
exit 1
}
fi
if [ ! -d "$DATA_DIR/stacks" ]; then
mkdir -p "$DATA_DIR/stacks" 2>/dev/null || true
fi
SOCKET_PATH="/var/run/docker.sock"
if [ -S "$SOCKET_PATH" ]; then
if test -r "$SOCKET_PATH" 2>/dev/null; then
echo "Docker socket accessible at $SOCKET_PATH"
if [ -z "$DOCKHAND_HOSTNAME" ]; then
DETECTED_HOSTNAME=$(curl -s --unix-socket "$SOCKET_PATH" http://localhost/info 2>/dev/null | sed -n 's/.*"Name":"\([^"]*\)".*/\1/p')
if [ -n "$DETECTED_HOSTNAME" ]; then
export DOCKHAND_HOSTNAME="$DETECTED_HOSTNAME"
echo "Detected Docker host hostname: $DOCKHAND_HOSTNAME"
fi
fi
else
SOCKET_GID=$(stat -c '%g' "$SOCKET_PATH" 2>/dev/null || echo "unknown")
echo "WARNING: Docker socket not readable by user $(id -u)"
echo "Add --group-add $SOCKET_GID to your docker run command"
fi
else
echo "No Docker socket found at $SOCKET_PATH"
echo "Configure Docker environments via the web UI (Settings > Environments)"
fi
if [ "$1" = "" ]; then
exec $DEFAULT_CMD
else
exec "$@"
fi
fi
# === User Setup ===
if [ "$PUID" = "0" ]; then
echo "Running as root user (PUID=0)"
RUN_USER="root"
elif [ "$RUNNING_AS_ROOT" = "true" ] && [ "$PUID" = "1001" ] && [ "$PGID" = "1001" ]; then
echo "Running as root user"
RUN_USER="root"
else
RUN_USER="dockhand"
if [ "$PUID" != "1001" ] || [ "$PGID" != "1001" ]; then
echo "Configuring user with PUID=$PUID PGID=$PGID"
deluser dockhand 2>/dev/null || true
delgroup dockhand 2>/dev/null || true
SKIP_USER_CREATE=false
EXISTING=$(awk -F: -v uid="$PUID" '$3 == uid { print $1 }' /etc/passwd)
if [ -n "$EXISTING" ]; then
echo "WARNING: UID $PUID already in use by '$EXISTING'. Using default UID 1001."
PUID=1001
fi
TARGET_GROUP=$(awk -F: -v gid="$PGID" '$3 == gid { print $1 }' /etc/group)
if [ -z "$TARGET_GROUP" ]; then
addgroup -g "$PGID" dockhand
TARGET_GROUP="dockhand"
fi
if [ "$SKIP_USER_CREATE" = "false" ]; then
adduser -u "$PUID" -G "$TARGET_GROUP" -h /home/dockhand -D dockhand
fi
fi
# === Directory Ownership ===
# Only chown Dockhand's own subdirectories, not the entire /app/data tree.
# Recursive chown on /app/data breaks stack volumes mounted with relative paths
# (e.g. ./postgresql:/var/lib/postgresql) that need different ownership (#719).
DATA_DIR="${DATA_DIR:-/app/data}"
chown "$RUN_USER":"$RUN_USER" "$DATA_DIR" 2>/dev/null || true
for subdir in db stacks git-repos tmp icons snapshots scanner-cache; do
if [ -d "$DATA_DIR/$subdir" ]; then
chown -R "$RUN_USER":"$RUN_USER" "$DATA_DIR/$subdir" 2>/dev/null || true
fi
done
if [ "$RUN_USER" = "dockhand" ]; then
chown -R dockhand:dockhand /home/dockhand 2>/dev/null || true
fi
if [ -n "$DATA_DIR" ] && [ "$DATA_DIR" != "/app/data" ] && [ "$DATA_DIR" != "./data" ]; then
mkdir -p "$DATA_DIR"
chown "$RUN_USER":"$RUN_USER" "$DATA_DIR" 2>/dev/null || true
for subdir in db stacks git-repos tmp icons snapshots scanner-cache; do
if [ -d "$DATA_DIR/$subdir" ]; then
chown -R "$RUN_USER":"$RUN_USER" "$DATA_DIR/$subdir" 2>/dev/null || true
fi
done
fi
fi
# === Docker Socket Access ===
SOCKET_PATH="/var/run/docker.sock"
if [ -S "$SOCKET_PATH" ]; then
if [ "$RUN_USER" != "root" ]; then
SOCKET_GID=$(stat -c '%g' "$SOCKET_PATH" 2>/dev/null || echo "")
if [ -n "$SOCKET_GID" ]; then
if ! su-exec "$RUN_USER" test -r "$SOCKET_PATH" 2>/dev/null; then
echo "Docker socket GID: $SOCKET_GID - adding $RUN_USER to docker group..."
DOCKER_GROUP=$(awk -F: -v gid="$SOCKET_GID" '$3 == gid { print $1 }' /etc/group)
if [ -z "$DOCKER_GROUP" ]; then
DOCKER_GROUP="docker"
addgroup -g "$SOCKET_GID" "$DOCKER_GROUP" 2>/dev/null || true
fi
addgroup "$RUN_USER" "$DOCKER_GROUP" 2>/dev/null || \
adduser "$RUN_USER" "$DOCKER_GROUP" 2>/dev/null || true
if su-exec "$RUN_USER" test -r "$SOCKET_PATH" 2>/dev/null; then
echo "Docker socket accessible at $SOCKET_PATH"
else
echo "WARNING: Could not grant Docker socket access to $RUN_USER"
echo "Try running container with: --group-add $SOCKET_GID"
fi
else
echo "Docker socket accessible at $SOCKET_PATH"
fi
fi
else
echo "Docker socket accessible at $SOCKET_PATH"
fi
if [ -z "$DOCKHAND_HOSTNAME" ]; then
DETECTED_HOSTNAME=$(curl -s --unix-socket "$SOCKET_PATH" http://localhost/info 2>/dev/null | sed -n 's/.*"Name":"\([^"]*\)".*/\1/p')
if [ -n "$DETECTED_HOSTNAME" ]; then
export DOCKHAND_HOSTNAME="$DETECTED_HOSTNAME"
echo "Detected Docker host hostname: $DOCKHAND_HOSTNAME"
fi
else
echo "Using configured hostname: $DOCKHAND_HOSTNAME"
fi
else
echo "No local Docker socket mounted (this is normal when using socket-proxy or remote Docker)"
echo "Configure your Docker environment via the web UI: Settings > Environments"
fi
# === Run Application ===
if [ "$RUN_USER" = "root" ]; then
if [ "$1" = "" ]; then
exec $DEFAULT_CMD
else
exec "$@"
fi
else
echo "Running as user: $RUN_USER"
if [ "$1" = "" ]; then
exec su-exec "$RUN_USER" $DEFAULT_CMD
else
exec su-exec "$RUN_USER" "$@"
fi
fi