Docker: Build Optimization and Enhanced Non-Root/Volumeless Support (#5024)
* docker: optimize build layers and enhance permission handling - Pre-created hardcoded dirs in Dockerfile to support volumeless non-root runs. - Enhanced slightly docker-entrypoint.sh with robust volume detection and safer chown logic. - Included legacy 'backups' directory... again. - Added dos2unix to install list. - Updated .dockerignore - Updated comments - Smaller fixes * fix(docker): removed unnecessary comment, and the... *sighs* backups dir, again * Exclude DS_Store everywhere * Exclude tests and all jsconfigs from docker images * Exclude local plugins from docker builds * fix(docker): backups are back... yay xD * feat(docker): add robust healthcheck script - Added `docker/healthcheck.cjs`: A standalone, dependency-free Node.js script for verifying server status. - Updated `Dockerfile`: Added HEALTHCHECK instruction and script copy step. - Features: Auto-detects port from env/config, handles IPv4/IPv6 fallback, auto-retries HTTPS on socket hangup, and sets custom User-Agent. * Fix .dockerignore permission * Revert "feat(docker): add robust healthcheck script" This reverts commit fa634fb08884cdef9245a12271cb9a13b487365f. --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
This commit is contained in:
+55
-15
@@ -1,21 +1,61 @@
|
||||
# --- Git & CI ---
|
||||
.git
|
||||
.github
|
||||
.vscode
|
||||
node_modules
|
||||
npm-debug.log
|
||||
readme*
|
||||
Start.bat
|
||||
/dist
|
||||
/backups
|
||||
cloudflared.exe
|
||||
access.log
|
||||
/data
|
||||
/cache
|
||||
.DS_Store
|
||||
/public/scripts/extensions/third-party
|
||||
/colab
|
||||
.gemini
|
||||
.gitignore
|
||||
|
||||
# --- Docker ---
|
||||
/Dockerfile
|
||||
/.dockerignore
|
||||
/docker/docker-compose.yml
|
||||
/docker/config
|
||||
/docker/extensions
|
||||
/docker/data
|
||||
/docker/plugins
|
||||
/public/scripts/extensions/third-party
|
||||
|
||||
# --- Plugins (keep only package files) ---
|
||||
/plugins/*
|
||||
!/plugins/package.json
|
||||
!/plugins/package-lock.json
|
||||
|
||||
# --- The Folders ---
|
||||
/backups
|
||||
/cache
|
||||
/colab
|
||||
/data
|
||||
/dist
|
||||
/node_modules
|
||||
/tests
|
||||
|
||||
# --- Sensitive Info ---
|
||||
**/.env*
|
||||
**/*.pem
|
||||
**/certs
|
||||
|
||||
# --- Documentation ---
|
||||
readme*
|
||||
*.md
|
||||
Update-Instructions.txt
|
||||
|
||||
# --- OS & System Junk ---
|
||||
**/.DS_Store
|
||||
*.bat
|
||||
*.cmd
|
||||
*.exe
|
||||
start.sh
|
||||
|
||||
# --- Dev Config ---
|
||||
.editorconfig
|
||||
.eslintrc.cjs
|
||||
.eslintrc*
|
||||
.vscode
|
||||
**/jsconfig.json
|
||||
.npmignore
|
||||
.gemini
|
||||
replit.nix
|
||||
.replit
|
||||
.nomedia
|
||||
|
||||
# -- Logs & Temp ---
|
||||
*.log
|
||||
**/tmp
|
||||
|
||||
+10
-10
@@ -4,8 +4,8 @@ FROM node:lts-alpine3.23
|
||||
ARG APP_HOME=/home/node/app
|
||||
|
||||
# Install system dependencies
|
||||
# Added su-exec and shadow to support optional PUID/PGID user mapping
|
||||
RUN apk add --no-cache gcompat tini git git-lfs su-exec shadow
|
||||
# "Don't rely on the base image for tools; if you call it, you install it." ;)
|
||||
RUN apk add --no-cache gcompat tini git git-lfs su-exec shadow dos2unix
|
||||
|
||||
# Create app directory and set ownership
|
||||
WORKDIR ${APP_HOME}
|
||||
@@ -21,28 +21,28 @@ RUN \
|
||||
echo "*** Install npm packages ***" && \
|
||||
npm ci --no-audit --no-fund --loglevel=error --no-progress --omit=dev && npm cache clean --force
|
||||
|
||||
# Create config directory and link config.yaml
|
||||
# Create config directory and link config.yaml. Added hardcoded dirs(constants.js?)
|
||||
# that must be present for Non-Root Mode and volumeless docker runs.
|
||||
RUN \
|
||||
rm -f "config.yaml" || true && \
|
||||
ln -s "./config/config.yaml" "config.yaml" || true && \
|
||||
mkdir "config" || true
|
||||
# Set ownership
|
||||
RUN chown -R node:node config
|
||||
mkdir -p config data plugins public/scripts/extensions/third-party backups && \
|
||||
chown -R node:node config data plugins public/scripts/extensions/third-party backups && \
|
||||
ln -s "./config/config.yaml" "config.yaml"
|
||||
|
||||
# Pre-compile public libraries
|
||||
RUN \
|
||||
echo "*** Run Webpack ***" && \
|
||||
node "./docker/build-lib.js"
|
||||
|
||||
# Set the entrypoint script
|
||||
# Set the entrypoint script and cleanup
|
||||
RUN \
|
||||
echo "*** Cleanup ***" && \
|
||||
mv "./docker/docker-entrypoint.sh" "./" && \
|
||||
rm -rf "./docker" && \
|
||||
echo "*** Make docker-entrypoint.sh executable ***" && \
|
||||
chmod +x "./docker-entrypoint.sh" && \
|
||||
echo "*** Convert line endings to Unix format ***" && \
|
||||
dos2unix "./docker-entrypoint.sh"
|
||||
dos2unix "./docker-entrypoint.sh" && \
|
||||
rm -rf "./docker"
|
||||
|
||||
# Fix extension repos permissions
|
||||
RUN git config --global --add safe.directory "*"
|
||||
|
||||
+13
-20
@@ -8,7 +8,7 @@ start_sillytavern() {
|
||||
# Config Check
|
||||
if [ ! -e "config/config.yaml" ]; then
|
||||
echo "Resource not found, copying from defaults: config.yaml"
|
||||
$PREFIX cp -r "default/config.yaml" "config/config.yaml"
|
||||
$PREFIX cp "default/config.yaml" "config/config.yaml"
|
||||
fi
|
||||
|
||||
# Execute postinstall to auto-populate config.yaml with missing values
|
||||
@@ -20,7 +20,7 @@ start_sillytavern() {
|
||||
|
||||
# Dirs that MUST be present at this point (e.g for volumeless docker runs).
|
||||
# Please update list, if in the future a related perm issue appear.
|
||||
CORE_DIRS="config data plugins public/scripts/extensions/third-party"
|
||||
CORE_DIRS="config data plugins public/scripts/extensions/third-party backups"
|
||||
|
||||
# Mounted Volumes (External)
|
||||
# Parse mounts, handling files vs directories
|
||||
@@ -35,11 +35,7 @@ for mount in $RAW_MOUNTS; do
|
||||
|
||||
# Performance Safety: If the file is in the root of the app,
|
||||
# we do NOT add the parent (App Root), or we will recursively scan the whole app.
|
||||
if [ "$PARENT_DIR" = "/home/node/app" ]; then
|
||||
MOUNTED_DIRS="$MOUNTED_DIRS $mount"
|
||||
else
|
||||
MOUNTED_DIRS="$MOUNTED_DIRS $PARENT_DIR"
|
||||
fi
|
||||
[ "$PARENT_DIR" != "/home/node/app" ] && MOUNTED_DIRS="$MOUNTED_DIRS $PARENT_DIR" || MOUNTED_DIRS="$MOUNTED_DIRS $mount"
|
||||
else
|
||||
# It is a directory, add it directly
|
||||
MOUNTED_DIRS="$MOUNTED_DIRS $mount"
|
||||
@@ -53,21 +49,19 @@ CHECK_DIRS=$(echo "$CORE_DIRS $MOUNTED_DIRS" | tr ' ' '\n' | sort -u)
|
||||
for dir in $CHECK_DIRS; do
|
||||
if [ ! -e "$dir" ]; then
|
||||
echo "Creating missing directory: $dir"
|
||||
mkdir -p "$dir"
|
||||
mkdir -p "$dir" 2>/dev/null || echo "Warning: Could not create $dir" >&2
|
||||
fi
|
||||
done
|
||||
|
||||
# Change permissions only if started as Root(UID 0) and needed.
|
||||
# Mode Selection
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
# Check if PUID/PGID variables are provided
|
||||
if [ -n "$PUID" ] && [ -n "$PGID" ]; then
|
||||
TARGET_UID=$PUID
|
||||
TARGET_GID=$PGID
|
||||
echo "Non-root mode requested (UID:$TARGET_UID GID:$TARGET_GID)."
|
||||
echo "Mode: PUID/PGID (UID:$PUID GID:$PGID)"
|
||||
|
||||
# Update the internal 'node' user to match requested IDs
|
||||
groupmod -o -g "$TARGET_GID" node
|
||||
usermod -o -u "$TARGET_UID" -g "$TARGET_GID" node
|
||||
groupmod -o -g "$PGID" node
|
||||
usermod -o -u "$PUID" -g "$PGID" node
|
||||
|
||||
for dir in $CHECK_DIRS; do
|
||||
if [ -d "$dir" ]; then
|
||||
@@ -75,11 +69,9 @@ if [ "$(id -u)" = "0" ]; then
|
||||
DIR_UID=$(stat -c '%u' "$dir")
|
||||
DIR_GID=$(stat -c '%g' "$dir")
|
||||
|
||||
if [ "$DIR_UID" != "$TARGET_UID" ] || [ "$DIR_GID" != "$TARGET_GID" ]; then
|
||||
if [ "$DIR_UID" != "$PUID" ] || [ "$DIR_GID" != "$PGID" ]; then
|
||||
echo "(Detected mismatch) Adjusting permissions for: $dir."
|
||||
if ! chown -R node:node "$dir"; then
|
||||
echo "Error: Failed to update permissions for '$dir'."
|
||||
fi
|
||||
chown -R node:node "$dir" || echo "Warning: Failed to update permissions for '$dir'." >&2
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -87,16 +79,17 @@ if [ "$(id -u)" = "0" ]; then
|
||||
# Fix config file specifically
|
||||
chown node:node "config/config.yaml" 2>/dev/null
|
||||
|
||||
# Set execution prefix to run as 'node' user
|
||||
EXEC_PREFIX="su-exec node:node"
|
||||
else
|
||||
# Default: Run as Root (original behavior)
|
||||
echo "Running in default (root) mode."
|
||||
echo "Mode: Default (Root)"
|
||||
EXEC_PREFIX=""
|
||||
fi
|
||||
|
||||
else
|
||||
# Non-Root Mode (Docker CLI --user flag)
|
||||
echo "Running as detected user (UID: $(id -u))."
|
||||
echo "Mode: Strict Non-Root (UID: $(id -u))"
|
||||
# We CANNOT auto-fix permissions in this mode because we lack privileges.
|
||||
# Relying solely on the user configuring their host permissions correctly.
|
||||
EXEC_PREFIX=""
|
||||
|
||||
Reference in New Issue
Block a user