-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
102 lines (98 loc) · 3.78 KB
/
Copy pathdocker-compose.yml
File metadata and controls
102 lines (98 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
services:
# Prebuilt by .github/workflows/build-images.yml on every merge to main; nodes
# pull it rather than building from source (see scripts/install.sh). Blank
# OBS_IMAGE_TAG tracks :latest -- set it to sha-<short> in .env to pin a node
# to a specific build without editing this file.
api:
image: ghcr.io/streamwizard/obs-instance-manager:${OBS_IMAGE_TAG:-latest}
container_name: obs-panel-api
restart: unless-stopped
ports:
# Never published on the LAN or a public interface. Two bindings:
# - loopback, for sidecars on the same host -- the Cloudflare Tunnel
# (cloudflared origin http://localhost:3000) is how browsers and the
# panel apps reach the node, with no dependency on Tailscale;
# - the Tailscale address, for tailnet hosts (alert worker, web-admin
# health probes, admins) -- the panel fills obs_nodes.api_url with
# http://<tailscale-ip>:3000 at link time as the default, and the
# admin overrides it with the tunnel hostname.
# The `:?` makes compose refuse to start when TAILSCALE_IP is blank: an
# empty host IP would silently mean 0.0.0.0, and Docker-published ports
# bypass ufw, so there is no second line of defence. Local dev in a
# checkout: set TAILSCALE_IP=127.0.0.1 in .env (duplicate binding is
# harmless).
- "127.0.0.1:3000:3000"
- "${TAILSCALE_IP:?TAILSCALE_IP must be set in .env (tailscale ip -4)}:3000:3000"
env_file:
- .env
environment:
- CADVISOR_URL=http://cadvisor:8080
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=utility,compute
- OBS_NETWORK=obs-net
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /data/obs-configs:/data/obs-configs
- /data/obs-plugins:/data/obs-plugins
gpus: all
networks:
- internal
- obs-net
depends_on:
- cadvisor
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
privileged: true
devices:
- /dev/kmsg
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
networks:
- internal
# The one real, GPU-bound Xorg for this machine's physical GPU (see
# ROLE=gpu-xserver in obs-cloud-container's entrypoint.sh). NVIDIA only
# allows one exclusive DRM master per physical GPU, so every obs-instance-*
# container shares this single X server via VirtualGL (`vglrun`) instead of
# each running its own GPU-bound Xorg -- which is what used to crash-loop
# every instance after the first. One compose stack = one machine = one
# GPU today, so this is a plain static service, not something the API needs
# to provision/manage itself.
gpu-xserver:
image: ghcr.io/streamwizard/obs-cloud-container:latest
container_name: gpu-xserver
restart: unless-stopped
runtime: nvidia
environment:
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=all
- ROLE=gpu-xserver
- GPU_BUSID=${GPU_BUSID:-PCI:0:16:0}
- RESOLUTION=1920x1080
volumes:
- gpu-x11-socket:/tmp/.X11-unix
# No SYS_ADMIN/NET_ADMIN/SYS_PTRACE/unconfined apparmor+seccomp here:
# this container never runs bwrap (no OBS, no browser-source jail).
networks:
internal:
driver: bridge
obs-net:
name: obs-net
driver: bridge
volumes:
# Explicit fixed name so obs-instance-manager's own container-creation
# code (src/clients/docker.ts) can reference it by a stable name,
# independent of this compose project's name.
gpu-x11-socket:
name: gpu-x11-socket