Files
henrytherobotandClaude Opus 5.5 41a894bffb compose: mount /unitree/var/run instead of the socket file; warn when mscli fails
master_service unlinks and recreates master_service.sock on every host boot
or restart, and a bind mount of the file pins the old (dead) inode, so every
mscli call inside the container failed with "Connect to server error".
Mount the directory instead. The entrypoint wraps "mscli stopservice
video_hub_pc4" in stop_videohub(), which prints a WARN when mscli cannot
reach master_service (then /dev/video4 stays busy and the camera will not
open), at start and in the 10 s loop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:23:06 +02:00

117 lines
3.7 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
services:
# -- NATS Server ----------------------------
nats:
image: nats:latest
profiles: ["nats"]
ports:
- "4222:4222"
- "8222:8222"
command: >
--auth ${NATS_TOKEN:-realsense-dev-token}
--http_port 8222
restart: unless-stopped
healthcheck:
test: ["CMD", "nats-server", "--help"]
interval: 5s
timeout: 3s
retries: 3
start_period: 5s
# -- Backend --------------------------------
backend:
build:
context: .
dockerfile: Dockerfile
# network: host so that build-time apt/git/pip can reach the
# tinyproxy running on the host at localhost:8888.
network: host
privileged: true
ports:
- "${API_PORT:-8878}:8878"
devices:
- "/dev/bus/usb:/dev/bus/usb"
volumes:
- ./images:/app/images
- ./models:/app/models:ro
# mscli + master_service socket so the container can stop the
# Unitree video_hub_pc4 service (it holds /dev/video4 — the D435i
# V4L2 node — and would otherwise make Open() fail with EBUSY).
# Mount the *directory*, not the socket file: master_service unlinks
# and recreates the socket on every host boot/restart, and a bind
# mount of the file pins the old (now dead) inode, so every mscli
# call inside the container fails with "Connect to server error".
- /unitree/sbin/mscli:/unitree/sbin/mscli:ro
- /unitree/var/run:/unitree/var/run
entrypoint:
- bash
- -c
- |
stop_videohub() {
out=$$(/unitree/sbin/mscli stopservice video_hub_pc4 2>&1) || true
case "$$out" in
*"Connect to server error"*|*"connect error"*)
echo "[entrypoint] WARN mscli cannot reach master_service.sock:" \
"/dev/video4 will stay busy and the camera will not open. $$out" >&2 ;;
esac
}
stop_videohub
sleep 2
( while sleep 10; do stop_videohub; done ) &
exec /app/entrypoint.sh
env_file: .env
depends_on:
nats:
condition: service_healthy
required: false
restart: unless-stopped
labels:
# autoheal monitora SOLO i container con questa label = true
autoheal: "true"
healthcheck:
# Healthcheck "vero": fallisce se camera_open != true.
# Usa /api/health (pubblico, no API key) che già ritorna camera_open.
# 4 retry × 15s ⇒ ~1 min di stato cattivo prima dell'autoheal restart.
test:
- CMD
- python3
- -c
- |
import urllib.request, json, sys
try:
r = urllib.request.urlopen('http://localhost:8878/api/health', timeout=3)
d = json.loads(r.read())
sys.exit(0 if d.get('data', {}).get('camera_open') else 1)
except Exception:
sys.exit(1)
interval: 15s
timeout: 5s
retries: 4
start_period: 30s
# -- Autoheal -------------------------------
# Monitora i container con label `autoheal=true` e li restarta automaticamente
# quando Docker li marca "unhealthy". Risolve il caso "pyrealsense2 SDK stuck".
autoheal:
image: willfarrell/autoheal:latest
container_name: autoheal-d435
restart: always
environment:
AUTOHEAL_CONTAINER_LABEL: autoheal
AUTOHEAL_INTERVAL: 10
AUTOHEAL_START_PERIOD: 30
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
# -- Frontend React Dev (hot reload) --------
frontend-dev:
image: node:20-alpine
working_dir: /app
volumes:
- ./src/frontend/react:/app
- /app/node_modules
command: sh -c "npm ci && npm run dev -- --host 0.0.0.0"
ports:
- "5173:5173"
profiles: [dev]