Dmitry Beresnev commited on
Commit
66a2fe2
·
1 Parent(s): edd7841

add openclaw and streamlit ui like separate services

Browse files
Files changed (4) hide show
  1. Caddyfile +9 -0
  2. Dockerfile +6 -2
  3. app.py +16 -2
  4. 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.13-slim
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 ["sh", "-c", "${OPENCLAW_BIN} gateway run --port ${OPENCLAW_PORT} --allow-unconfigured > /tmp/openclaw-gateway.log 2>&1 & exec uv run streamlit run app.py --server.address=0.0.0.0 --server.port=7860"]
 
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
- st.metric("Gateway Status", "Running" if proc else "Stopped")
 
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