diff --git a/install.md b/install.md index bd880f7..2f3eea4 100644 --- a/install.md +++ b/install.md @@ -85,15 +85,20 @@ Pre-pulling is required. MCP servers have a short initialization timeout - if Do **Step 2 - Start the persistent container (one-time setup):** -If a `hyperstack-mcp` container already exists from a previous install, delete it first to ensure a clean state with the latest image: +Hyperstack enforces a **singleton container policy**. If a `hyperstack-mcp` container exists OR any container is running from the `hyperstack:main` image, it must be removed before starting a fresh one to ensure no stale state persists. +Run the provided singleton enforcement script: ```bash -docker rm -f hyperstack-mcp 2>/dev/null # safe: no-op if container doesn't exist +bash scripts/ensure-singleton.sh ``` -Then create the fresh container: +Or run the hard check manually: ```bash +# 1. Remove ANY container based on the hyperstack image +docker ps -aq --filter "ancestor=ghcr.io/orkait/hyperstack:main" | xargs -r docker rm -f + +# 2. Run the fresh singleton container docker run -d --name hyperstack-mcp --restart unless-stopped \ --memory=512m --cpus=1 \ --entrypoint sleep \ diff --git a/package.json b/package.json index fcf7f4f..59c01f4 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "compile:context": "bun src/internal/compile-runtime-context.ts", "test": "bun test", "start": "bun src/index.ts", - "dev": "bun --watch src/index.ts" + "dev": "bun --watch src/index.ts", + "docker:run": "bash scripts/ensure-singleton.sh" }, "author": "Orkait", "license": "MIT", diff --git a/scripts/ensure-singleton.sh b/scripts/ensure-singleton.sh new file mode 100755 index 0000000..51933d6 --- /dev/null +++ b/scripts/ensure-singleton.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Hard check to ensure only one Hyperstack container is running. +# Removes all previous instances (by name or image) before starting a fresh one. + +IMAGE="ghcr.io/orkait/hyperstack:main" +CONTAINER_NAME="hyperstack-mcp" + +echo "Checking for existing Hyperstack containers..." + +# 1. Find containers by the specific image +BY_IMAGE=$(docker ps -aq --filter "ancestor=$IMAGE") + +# 2. Find containers by name +BY_NAME=$(docker ps -aq --filter "name=$CONTAINER_NAME") + +# Combine and remove duplicates +ALL_STALE=$(echo "$BY_IMAGE $BY_NAME" | xargs -n1 | sort -u) + +if [ -n "$ALL_STALE" ]; then + echo "Removing stale Hyperstack containers: $ALL_STALE" + docker rm -f $ALL_STALE 2>/dev/null +else + echo "No stale containers found." +fi + +echo "Starting fresh Hyperstack container: $CONTAINER_NAME" +docker run -d --name "$CONTAINER_NAME" --restart unless-stopped \ + --memory=512m --cpus=1 \ + --entrypoint sleep \ + "$IMAGE" infinity + +echo "Verification:" +docker ps --filter name="$CONTAINER_NAME"