Spaces:
Build error
Build error
Dmitry Beresnev commited on
Commit ·
66a2fe2
1
Parent(s): edd7841
add openclaw and streamlit ui like separate services
Browse files- Caddyfile +9 -0
- Dockerfile +6 -2
- app.py +16 -2
- supervisord.conf +26 -0
Caddyfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
:{$PORT}
|
| 2 |
+
|
| 3 |
+
handle_path /openclaw/* {
|
| 4 |
+
reverse_proxy 127.0.0.1:{$OPENCLAW_PORT}
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
handle {
|
| 8 |
+
reverse_proxy 127.0.0.1:8501
|
| 9 |
+
}
|
Dockerfile
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
FROM python:3.
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
|
@@ -7,8 +7,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
| 7 |
bash \
|
| 8 |
curl \
|
| 9 |
ca-certificates \
|
|
|
|
| 10 |
ffmpeg \
|
| 11 |
git \
|
|
|
|
| 12 |
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
| 13 |
&& apt-get install -y --no-install-recommends nodejs \
|
| 14 |
&& npm install -g openclaw \
|
|
@@ -31,9 +33,11 @@ ENV VAULT_PATH=/app/vault
|
|
| 31 |
ENV OPENCLAW_HOME=/app/.openclaw
|
| 32 |
ENV OPENCLAW_STATE_DIR=/app/.openclaw/state
|
| 33 |
ENV AUTO_START_GATEWAY=0
|
|
|
|
|
|
|
| 34 |
|
| 35 |
RUN mkdir -p /app/vault /app/.openclaw/state
|
| 36 |
|
| 37 |
EXPOSE 7860
|
| 38 |
|
| 39 |
-
CMD ["
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
|
|
|
| 7 |
bash \
|
| 8 |
curl \
|
| 9 |
ca-certificates \
|
| 10 |
+
caddy \
|
| 11 |
ffmpeg \
|
| 12 |
git \
|
| 13 |
+
supervisor \
|
| 14 |
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
| 15 |
&& apt-get install -y --no-install-recommends nodejs \
|
| 16 |
&& npm install -g openclaw \
|
|
|
|
| 33 |
ENV OPENCLAW_HOME=/app/.openclaw
|
| 34 |
ENV OPENCLAW_STATE_DIR=/app/.openclaw/state
|
| 35 |
ENV AUTO_START_GATEWAY=0
|
| 36 |
+
ENV EXTERNAL_GATEWAY_MANAGED=1
|
| 37 |
+
ENV OPENCLAW_STANDARD_UI_PUBLIC_URL=/openclaw/
|
| 38 |
|
| 39 |
RUN mkdir -p /app/vault /app/.openclaw/state
|
| 40 |
|
| 41 |
EXPOSE 7860
|
| 42 |
|
| 43 |
+
CMD ["supervisord", "-c", "/app/supervisord.conf"]
|
app.py
CHANGED
|
@@ -28,9 +28,10 @@ LOG_MAX_LINES = 300
|
|
| 28 |
OPENCLAW_STANDARD_UI_URL = os.getenv(
|
| 29 |
"OPENCLAW_STANDARD_UI_URL", f"http://127.0.0.1:{OPENCLAW_PORT}/"
|
| 30 |
)
|
| 31 |
-
OPENCLAW_STANDARD_UI_PUBLIC_URL = os.getenv("OPENCLAW_STANDARD_UI_PUBLIC_URL", "")
|
| 32 |
OPENCLAW_GATEWAY_TOKEN = os.getenv("OPENCLAW_GATEWAY_TOKEN", "")
|
| 33 |
GATEWAY_BOOT_LOG_PATH = Path(os.getenv("OPENCLAW_GATEWAY_LOG_PATH", "/tmp/openclaw-gateway.log"))
|
|
|
|
| 34 |
|
| 35 |
|
| 36 |
def resolve_openclaw_bin() -> str | None:
|
|
@@ -118,6 +119,8 @@ def pull_boot_logs() -> None:
|
|
| 118 |
|
| 119 |
|
| 120 |
def start_gateway() -> tuple[bool, str]:
|
|
|
|
|
|
|
| 121 |
if gateway_process() is not None:
|
| 122 |
return True, "Gateway is already running."
|
| 123 |
|
|
@@ -191,6 +194,8 @@ def start_gateway() -> tuple[bool, str]:
|
|
| 191 |
|
| 192 |
|
| 193 |
def stop_gateway() -> tuple[bool, str]:
|
|
|
|
|
|
|
| 194 |
proc = gateway_process()
|
| 195 |
if proc is None:
|
| 196 |
return True, "Gateway is not running."
|
|
@@ -238,6 +243,12 @@ def test_gateway(query: str) -> str:
|
|
| 238 |
return f"Gateway request failed: {exc}"
|
| 239 |
|
| 240 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 241 |
def with_token(url: str, token: str) -> str:
|
| 242 |
if not token:
|
| 243 |
return url
|
|
@@ -327,7 +338,8 @@ if (
|
|
| 327 |
status_col, action_col = st.columns([2, 3])
|
| 328 |
with status_col:
|
| 329 |
proc = gateway_process()
|
| 330 |
-
|
|
|
|
| 331 |
st.write(f"UI port: `{HF_PORT}`")
|
| 332 |
st.write(f"Gateway port: `{OPENCLAW_PORT}`")
|
| 333 |
st.write(f"Vault path: `{VAULT_PATH}`")
|
|
@@ -349,6 +361,8 @@ with action_col:
|
|
| 349 |
(st.success if ok else st.error)(msg)
|
| 350 |
if c4.button("Refresh", use_container_width=True):
|
| 351 |
st.rerun()
|
|
|
|
|
|
|
| 352 |
|
| 353 |
st.divider()
|
| 354 |
|
|
|
|
| 28 |
OPENCLAW_STANDARD_UI_URL = os.getenv(
|
| 29 |
"OPENCLAW_STANDARD_UI_URL", f"http://127.0.0.1:{OPENCLAW_PORT}/"
|
| 30 |
)
|
| 31 |
+
OPENCLAW_STANDARD_UI_PUBLIC_URL = os.getenv("OPENCLAW_STANDARD_UI_PUBLIC_URL", "/openclaw/")
|
| 32 |
OPENCLAW_GATEWAY_TOKEN = os.getenv("OPENCLAW_GATEWAY_TOKEN", "")
|
| 33 |
GATEWAY_BOOT_LOG_PATH = Path(os.getenv("OPENCLAW_GATEWAY_LOG_PATH", "/tmp/openclaw-gateway.log"))
|
| 34 |
+
EXTERNAL_GATEWAY_MANAGED = os.getenv("EXTERNAL_GATEWAY_MANAGED", "0") == "1"
|
| 35 |
|
| 36 |
|
| 37 |
def resolve_openclaw_bin() -> str | None:
|
|
|
|
| 119 |
|
| 120 |
|
| 121 |
def start_gateway() -> tuple[bool, str]:
|
| 122 |
+
if EXTERNAL_GATEWAY_MANAGED:
|
| 123 |
+
return True, "Gateway is managed by supervisor from Docker startup."
|
| 124 |
if gateway_process() is not None:
|
| 125 |
return True, "Gateway is already running."
|
| 126 |
|
|
|
|
| 194 |
|
| 195 |
|
| 196 |
def stop_gateway() -> tuple[bool, str]:
|
| 197 |
+
if EXTERNAL_GATEWAY_MANAGED:
|
| 198 |
+
return False, "Gateway is managed by supervisor; stop it via container config."
|
| 199 |
proc = gateway_process()
|
| 200 |
if proc is None:
|
| 201 |
return True, "Gateway is not running."
|
|
|
|
| 243 |
return f"Gateway request failed: {exc}"
|
| 244 |
|
| 245 |
|
| 246 |
+
def is_gateway_port_open(timeout: float = 0.5) -> bool:
|
| 247 |
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
| 248 |
+
sock.settimeout(timeout)
|
| 249 |
+
return sock.connect_ex(("127.0.0.1", OPENCLAW_PORT)) == 0
|
| 250 |
+
|
| 251 |
+
|
| 252 |
def with_token(url: str, token: str) -> str:
|
| 253 |
if not token:
|
| 254 |
return url
|
|
|
|
| 338 |
status_col, action_col = st.columns([2, 3])
|
| 339 |
with status_col:
|
| 340 |
proc = gateway_process()
|
| 341 |
+
running = is_gateway_port_open() or (proc is not None)
|
| 342 |
+
st.metric("Gateway Status", "Running" if running else "Stopped")
|
| 343 |
st.write(f"UI port: `{HF_PORT}`")
|
| 344 |
st.write(f"Gateway port: `{OPENCLAW_PORT}`")
|
| 345 |
st.write(f"Vault path: `{VAULT_PATH}`")
|
|
|
|
| 361 |
(st.success if ok else st.error)(msg)
|
| 362 |
if c4.button("Refresh", use_container_width=True):
|
| 363 |
st.rerun()
|
| 364 |
+
if EXTERNAL_GATEWAY_MANAGED:
|
| 365 |
+
st.caption("Gateway controls are informational only (managed by Docker supervisor).")
|
| 366 |
|
| 367 |
st.divider()
|
| 368 |
|
supervisord.conf
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[supervisord]
|
| 2 |
+
nodaemon=true
|
| 3 |
+
logfile=/tmp/supervisord.log
|
| 4 |
+
pidfile=/tmp/supervisord.pid
|
| 5 |
+
|
| 6 |
+
[program:openclaw]
|
| 7 |
+
command=/bin/sh -lc "%(ENV_OPENCLAW_BIN)s gateway run --port %(ENV_OPENCLAW_PORT)s --allow-unconfigured"
|
| 8 |
+
autorestart=true
|
| 9 |
+
startsecs=2
|
| 10 |
+
stdout_logfile=/tmp/openclaw-gateway.log
|
| 11 |
+
stderr_logfile=/tmp/openclaw-gateway.err.log
|
| 12 |
+
environment=HOME="/root"
|
| 13 |
+
|
| 14 |
+
[program:streamlit]
|
| 15 |
+
command=/bin/sh -lc "cd /app && uv run streamlit run app.py --server.address=0.0.0.0 --server.port=8501"
|
| 16 |
+
autorestart=true
|
| 17 |
+
startsecs=2
|
| 18 |
+
stdout_logfile=/tmp/streamlit.log
|
| 19 |
+
stderr_logfile=/tmp/streamlit.err.log
|
| 20 |
+
|
| 21 |
+
[program:caddy]
|
| 22 |
+
command=/bin/sh -lc "caddy run --config /app/Caddyfile --adapter caddyfile"
|
| 23 |
+
autorestart=true
|
| 24 |
+
startsecs=2
|
| 25 |
+
stdout_logfile=/tmp/caddy.log
|
| 26 |
+
stderr_logfile=/tmp/caddy.err.log
|