129 行
3.3 KiB
Bash
可执行文件
129 行
3.3 KiB
Bash
可执行文件
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage:
|
|
run_in_docker.sh [runner options] -- [entrypoint args]
|
|
|
|
Runner options:
|
|
--build Build image before running
|
|
--image <name> Override image name (default: codex/similarweb-analytics:latest)
|
|
--runtime-dir <path> Host path that contains data_api.py (default: /opt/.manus/.sandbox-runtime)
|
|
--output-dir <path> Host output directory mounted to /data (default: ./similarweb-output)
|
|
--network <mode> Docker network mode (default: bridge)
|
|
-h, --help Show this message
|
|
|
|
Entrypoint args:
|
|
--self-test
|
|
--api <global-rank|visits-total|unique-visit|bounce-rate|traffic-sources-desktop|traffic-sources-mobile|traffic-by-country>
|
|
--domain <domain>
|
|
--start-date YYYY-MM
|
|
--end-date YYYY-MM
|
|
--country <country>
|
|
--granularity monthly
|
|
--limit <1..10>
|
|
--main-domain-only
|
|
--output /data/<file>.json
|
|
--dry-run
|
|
--mock-result
|
|
|
|
Examples:
|
|
run_in_docker.sh --build -- --self-test
|
|
run_in_docker.sh -- --api visits-total --domain amazon.com --dry-run
|
|
run_in_docker.sh -- --api global-rank --domain amazon.com --output /data/amazon-rank.json
|
|
EOF
|
|
}
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
IMAGE="${SIMILARWEB_IMAGE:-codex/similarweb-analytics:latest}"
|
|
RUNTIME_DIR="${SIMILARWEB_RUNTIME_DIR:-/opt/.manus/.sandbox-runtime}"
|
|
OUTPUT_DIR="${SIMILARWEB_OUTPUT_DIR:-$PWD/similarweb-output}"
|
|
NETWORK_MODE="${SIMILARWEB_NETWORK_MODE:-bridge}"
|
|
BUILD_IMAGE=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--build)
|
|
BUILD_IMAGE=1
|
|
shift
|
|
;;
|
|
--image)
|
|
IMAGE="${2:-}"
|
|
shift 2
|
|
;;
|
|
--runtime-dir)
|
|
RUNTIME_DIR="${2:-}"
|
|
shift 2
|
|
;;
|
|
--output-dir)
|
|
OUTPUT_DIR="${2:-}"
|
|
shift 2
|
|
;;
|
|
--network)
|
|
NETWORK_MODE="${2:-}"
|
|
shift 2
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown runner option: $1" >&2
|
|
usage >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ $# -eq 0 ]]; then
|
|
echo "Missing entrypoint args. Use -- to pass container args." >&2
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
echo "docker command not found" >&2
|
|
exit 127
|
|
fi
|
|
|
|
if [[ ! -d "$RUNTIME_DIR" ]]; then
|
|
echo "Runtime dir not found: $RUNTIME_DIR" >&2
|
|
echo "It must contain data_api.py for real API calls." >&2
|
|
exit 1
|
|
fi
|
|
if [[ ! -f "$RUNTIME_DIR/data_api.py" ]]; then
|
|
echo "Runtime module missing: $RUNTIME_DIR/data_api.py" >&2
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p "$OUTPUT_DIR"
|
|
# Keep container non-root while ensuring mounted output path is writable.
|
|
chmod 0777 "$OUTPUT_DIR" 2>/dev/null || true
|
|
|
|
if [[ "$BUILD_IMAGE" -eq 1 ]] || ! docker image inspect "$IMAGE" >/dev/null 2>&1; then
|
|
docker build -t "$IMAGE" -f "$SCRIPT_DIR/docker/Dockerfile" "$SCRIPT_DIR/docker"
|
|
fi
|
|
|
|
docker run --rm \
|
|
--network "$NETWORK_MODE" \
|
|
--read-only \
|
|
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
|
|
--tmpfs /var/tmp:rw,noexec,nosuid,size=32m \
|
|
--cap-drop ALL \
|
|
--security-opt no-new-privileges \
|
|
--pids-limit 256 \
|
|
--memory 512m \
|
|
--cpus 1.0 \
|
|
-e SIMILARWEB_API_KEY \
|
|
-e SIMILARWEB_BASE_URL \
|
|
-e RAPIDAPI_KEY \
|
|
-e RAPIDAPI_SIMILARWEB_HOST \
|
|
-v "$RUNTIME_DIR:/opt/.manus/.sandbox-runtime:ro" \
|
|
-v "$OUTPUT_DIR:/data:rw" \
|
|
"$IMAGE" "$@"
|