mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
98 lines
4.2 KiB
YAML
98 lines
4.2 KiB
YAML
# MultiRover production deployment
|
|
#
|
|
# The public application and private lifecycle controller reuse one published
|
|
# image. Only the lifecycle service receives Docker control; the application
|
|
# retains the narrower hardware access it needs at runtime.
|
|
name: multirover
|
|
|
|
# This is the deployment's single image selector. Production leaves it on
|
|
# latest; a development deployment can change this one line to its branch tag.
|
|
x-multirover-image: &multirover-image ghcr.io/legop3/multiroombarover:latest
|
|
|
|
services:
|
|
server:
|
|
image: *multirover-image
|
|
container_name: multirover
|
|
|
|
# Host networking preserves the server's existing LAN behavior and avoids
|
|
# maintaining a second list of TCP, UDP, RTSP, and WebRTC port mappings.
|
|
network_mode: host
|
|
restart: unless-stopped
|
|
stop_grace_period: 20s
|
|
|
|
# SELinux cannot safely relabel the host's system D-Bus socket, and the
|
|
# hardware services also need host-owned USB device nodes. Disable Docker's
|
|
# per-container SELinux label while retaining its namespace, capability,
|
|
# non-root-user, and seccomp isolation. This is narrower than privileged
|
|
# mode and avoids changing labels on shared host resources.
|
|
security_opt:
|
|
- label=disable
|
|
|
|
volumes:
|
|
# Docker owns the volume and initializes it from the image's non-root
|
|
# /data directory. This avoids coupling container permissions to a host
|
|
# account's numeric UID while keeping every persistent file together.
|
|
- data:/data
|
|
|
|
# The application can ask the private controller for one of its fixed
|
|
# lifecycle operations, but it never receives the Docker socket itself.
|
|
- lifecycle-socket:/run/multirover
|
|
|
|
# bluetoothctl talks to the host Bluetooth daemon over this socket. The
|
|
# socket is read-only as a filesystem mount; D-Bus method calls still flow
|
|
# through it normally without exposing the rest of the host D-Bus tree.
|
|
- /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro
|
|
|
|
# Kinect USB node numbers change when it reconnects, so expose the bus
|
|
# directory rather than one temporary device path. The existing host udev
|
|
# rule remains responsible for granting the non-root container user access.
|
|
devices:
|
|
- /dev/bus/usb:/dev/bus/usb
|
|
|
|
# Only the Balance Board worker receives this capability through its file
|
|
# capabilities. The Node process remains non-root and the container is not
|
|
# privileged.
|
|
cap_add:
|
|
- NET_ADMIN
|
|
|
|
lifecycle:
|
|
# Reuse the application image and override only its command. This keeps
|
|
# GHCR publishing and host deployment limited to one image and one Compose
|
|
# file while the Docker-authorized process remains isolated from the app.
|
|
image: *multirover-image
|
|
container_name: multirover-lifecycle
|
|
command: ["node", "src/services/serverControlService/controller.js"]
|
|
user: root
|
|
network_mode: none
|
|
restart: unless-stopped
|
|
# The shared image's health check targets the application HTTP server. This
|
|
# controller intentionally has no TCP listener, so it must not inherit it.
|
|
healthcheck:
|
|
disable: true
|
|
security_opt:
|
|
- label=disable
|
|
environment:
|
|
# Requests cannot override this deployment-owned target. Reusing the
|
|
# anchor guarantees the controller pulls the image used by the server.
|
|
MULTIROVER_TARGET_IMAGE: *multirover-image
|
|
volumes:
|
|
# Status survives replacement of the application and is kept under its
|
|
# existing single data boundary. The transient socket has its own volume
|
|
# so special filesystem entries never enter full-data backups.
|
|
- data:/data
|
|
- lifecycle-socket:/run/multirover
|
|
|
|
# This is host-root-equivalent access and therefore exists only here,
|
|
# never in the public-facing application container.
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
|
|
volumes:
|
|
# Use an explicit name so the same data volume survives Compose project moves
|
|
# or directory renames. Ordinary `docker compose down` does not remove it.
|
|
data:
|
|
name: multirover-data
|
|
# This volume carries only the private Unix socket and contains no durable
|
|
# application state. Docker creates it automatically with the deployment.
|
|
lifecycle-socket:
|
|
name: multirover-lifecycle-socket
|