openpencil/docker/entrypoint.sh

61 lines
2.3 KiB
Bash
Raw Permalink Normal View History

#!/bin/sh
# Entrypoint for the OpenPencil Vue container: runs the static SPA server on
# :3100 and the @open-pencil/mcp Streamable-HTTP server on :7600 in the same
# container. Forwards SIGTERM/SIGINT to both so docker stop is clean.
# POSIX sh only (no `wait -n`) — the runtime image is Alpine/dash.
set -eu
WEB_PORT="${OPENPENCIL_WEB_PORT:-3100}"
MCP_PORT="${OPENPENCIL_MCP_PORT:-7600}"
# The MCP server creates a Unix socket + discovery file by default. In the
# container we direct them under /data (writable volume) so the socket never
# collides with /run/user/... and documents land on the persisted volume.
export OPENPENCIL_MCP_ROOT="${OPENPENCIL_MCP_ROOT:-/data}"
export OPENPENCIL_MCP_SOCKET="${OPENPENCIL_MCP_SOCKET:-/data/mcp.sock}"
export OPENPENCIL_MCP_DISCOVERY_PATH="${OPENPENCIL_MCP_DISCOVERY_PATH:-/data/mcp.json}"
export OPENPENCIL_MCP_CORS_ORIGIN="${OPENPENCIL_MCP_CORS_ORIGIN:-}"
# Bind MCP on all interfaces so sibling containers (chatapi) can reach it by
# service name (openpencil:7600), not just via localhost port-forwarding.
export OPENPENCIL_MCP_HOST="${OPENPENCIL_MCP_HOST:-0.0.0.0}"
mkdir -p "$OPENPENCIL_MCP_ROOT" "$(dirname "$OPENPENCIL_MCP_SOCKET")" "$(dirname "$OPENPENCIL_MCP_DISCOVERY_PATH")"
echo "[openpencil] starting static SPA on :${WEB_PORT} and MCP on :${MCP_PORT}"
# Static SPA.
OPENPENCIL_WEB_PORT="$WEB_PORT" bun static-server.mjs &
WEB_PID=$!
# MCP server (Streamable HTTP at /mcp). Bun runs the node-targeted bin.
PORT="$MCP_PORT" bun packages/mcp/bin/openpencil-mcp-http.js &
MCP_PID=$!
shutdown() {
echo "[openpencil] shutting down (MCP=$MCP_PID, web=$WEB_PID) ..."
kill -TERM "$MCP_PID" "$WEB_PID" 2>/dev/null || true
exit 0
}
trap shutdown TERM INT
# Wait for both processes; stop the container when either exits.
STATUS=0
while :; do
WEB_ALIVE=0; MCP_ALIVE=0
kill -0 "$WEB_PID" 2>/dev/null && WEB_ALIVE=1
kill -0 "$MCP_PID" 2>/dev/null && MCP_ALIVE=1
if [ "$WEB_ALIVE" = "0" ] || [ "$MCP_ALIVE" = "0" ]; then
STATUS=1
break
fi
# Poll every second; a SIGTERM/SIGINT wakes the loop via the trap's exit.
sleep 1
done
echo "[openpencil] a child process exited; stopping the container"
kill -TERM "$MCP_PID" "$WEB_PID" 2>/dev/null || true
wait "$MCP_PID" 2>/dev/null || true
wait "$WEB_PID" 2>/dev/null || true
exit "$STATUS"