Exclude Python virtualenvs from the Docker build context (#7658)

# Description of Changes

Stirling engine docker slimming

Exclude Python virtualenvs from the Docker build context
Drop unused provider SDKs from the engine dependency set
Retry the SQLite WAL switch when workers race on startup
Build the engine image in two stages and run it unprivileged
Swap voyage SDK for api call removing 200MB bloat
Bundle the AI engine in the fat image
Publish the AI engine as a standalone image


886MB to 295MB in docker file

And Docker fat is only 230MB bigger after adding (since it already has
python and some deps)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
This commit is contained in:
Anthony Stirling
2026-08-24 16:23:55 +00:00
committed by GitHub
parent 158187ac46
commit ddee690c58
13 changed files with 575 additions and 1802 deletions
+43
View File
@@ -890,6 +890,11 @@ log "Setting permissions..."
mkdir -p /tmp/stirling-pdf /tmp/stirling-pdf/heap_dumps /logs /configs /configs/heap_dumps /configs/cache /customFiles /pipeline /storage || true
CHOWN_PATHS=("$HOME" "/logs" "/scripts" "/configs" "/customFiles" "/pipeline" "/storage" "/tmp/stirling-pdf" "/app.jar")
[ -d /usr/share/fonts/truetype ] && CHOWN_PATHS+=("/usr/share/fonts/truetype")
# Chowned here rather than at build time so it follows PUID/PGID remapping.
if [ -d "${STIRLING_ENGINE_HOME:-/opt/stirling-engine}" ]; then
mkdir -p "${STIRLING_ENGINE_HOME:-/opt/stirling-engine}/data" || true
CHOWN_PATHS+=("${STIRLING_ENGINE_HOME:-/opt/stirling-engine}/data")
fi
CHOWN_OK=true
for p in "${CHOWN_PATHS[@]}"; do
if [ -e "$p" ]; then
@@ -962,6 +967,38 @@ else
JAVA_CMD+=("org.springframework.boot.loader.launch.JarLauncher")
fi
# ---------- AI engine ----------
# Only the fat image ships it. The backend already defaults to http://localhost:5001.
STIRLING_ENGINE_HOME="${STIRLING_ENGINE_HOME:-/opt/stirling-engine}"
ENGINE_PID=""
if [ -x "$STIRLING_ENGINE_HOME/.venv/bin/python" ] && [ "${AIENGINE_ENABLED:-true}" = "false" ]; then
log "AI engine bundled but AIENGINE_ENABLED=false; not starting it."
elif [ -x "$STIRLING_ENGINE_HOME/.venv/bin/python" ]; then
log "Starting bundled AI engine on port ${STIRLING_ENGINE_PORT:-5001}..."
ENGINE_CMD=(
"$STIRLING_ENGINE_HOME/.venv/bin/python" -m uvicorn
stirling.api.app:app
--host 127.0.0.1
--port "${STIRLING_ENGINE_PORT:-5001}"
--workers "${STIRLING_ENGINE_WORKERS:-2}"
--app-dir "$STIRLING_ENGINE_HOME/src"
)
# init.sh exports PYTHONPATH for unoserver's 3.12 venv; inheriting it breaks the 3.13 engine.
if [ "$CURRENT_USER" = "$RUNTIME_USER" ]; then
env -u PYTHONPATH "${ENGINE_CMD[@]}" &
elif [ "$CURRENT_UID" -eq 0 ] && command_exists setpriv; then
env -u PYTHONPATH \
HOME="$(getent passwd "$RUNTIME_USER" | cut -d: -f6)" \
USER="$RUNTIME_USER" \
LOGNAME="$RUNTIME_USER" \
setpriv --reuid="$RUNTIME_USER" --regid="$(id -gn "$RUNTIME_USER")" --init-groups -- "${ENGINE_CMD[@]}" &
else
env -u PYTHONPATH "${ENGINE_CMD[@]}" &
fi
ENGINE_PID=$!
log "AI engine started (PID $ENGINE_PID)"
fi
if [ "$CURRENT_USER" = "$RUNTIME_USER" ]; then
"${JAVA_CMD[@]}" &
elif [ "$CURRENT_UID" -eq 0 ] && command_exists setpriv; then
@@ -1074,6 +1111,12 @@ fi
wait "$JAVA_PID" || true
exit_code=$?
if [ -n "$ENGINE_PID" ] && kill -0 "$ENGINE_PID" 2>/dev/null; then
log "Stopping AI engine (PID $ENGINE_PID)..."
kill "$ENGINE_PID" 2>/dev/null || true
wait "$ENGINE_PID" 2>/dev/null || true
fi
case "$exit_code" in
0) log "Stirling PDF exited normally." ;;
137) log "Stirling PDF was OOM-killed (exit 137). Check container memory limits." ;;