# Both containers share the host network so ROS 2 DDS discovery works without # any extra multicast configuration. Each container is given access only to # the specific device it needs rather than running in privileged mode. services: robot: build: context: ./raspbot_v2 dockerfile: Dockerfile platforms: - linux/arm64 image: raspbot_v2:latest network_mode: host ipc: host devices: - /dev/i2c-1:/dev/i2c-1 environment: - ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-0} # Required for ros2_control to set SCHED_FIFO real-time thread priority. # See https://control.ros.org/kilted/doc/ros2_control/controller_manager/doc/userdoc.html#determinism cap_add: - SYS_NICE ulimits: rtprio: 99 memlock: -1 restart: unless-stopped lidar: build: context: . dockerfile: lidar/Dockerfile platforms: - linux/amd64 - linux/arm64 image: raspbot_v2_lidar:latest network_mode: host ipc: host devices: - ${LIDAR_PORT:-/dev/ttyUSB0}:${LIDAR_PORT:-/dev/ttyUSB0} environment: - ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-0} command: - ros2 - launch - sllidar_ros2 - sllidar_a1_launch.py - serial_port:=${LIDAR_PORT:-/dev/ttyUSB0} - frame_id:=${LIDAR_FRAME_ID:-laser} - serial_baudrate:=115200 - angle_compensate:=true restart: unless-stopped oled: build: context: . dockerfile: oled/Dockerfile platforms: - linux/arm64 image: raspbot_v2_oled:latest network_mode: host ipc: host devices: - /dev/i2c-1:/dev/i2c-1 environment: - ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-0} restart: unless-stopped wifi: build: context: wifi dockerfile: Dockerfile platforms: - linux/arm64 image: raspbot_v2_wifi:latest network_mode: host cap_add: - NET_ADMIN volumes: - /run/dbus/system_bus_socket:/run/dbus/system_bus_socket environment: - WIFI_SSID=${WIFI_SSID:-} - HOTSPOT_SSID=${HOTSPOT_SSID:-raspbot-hotspot} - HOTSPOT_PASSWORD=${HOTSPOT_PASSWORD:-raspbot1234} - HOTSPOT_BAND=${HOTSPOT_BAND:-bg} - WIFI_IFACE=${WIFI_IFACE:-} - WIFI_TIMEOUT=${WIFI_TIMEOUT:-30} - POLL_INTERVAL=${POLL_INTERVAL:-15} restart: unless-stopped teleop: build: context: teleop dockerfile: Dockerfile platforms: - linux/amd64 - linux/arm64 image: raspbot_v2_teleop:latest network_mode: host ipc: host stdin_open: true tty: true devices: - ${JOYSTICK_DEV:-/dev/input/js0}:/dev/input/js0 - ${JOYSTICK2_DEV:-/dev/input/js1}:/dev/input/js1 - ${JOYSTICK_EVENT_DEV:-/dev/input/event0}:/dev/input/event0 environment: - ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-0} # Joystick config name — must match a file in teleop_twist_joy/config/ (without .config.yaml). # e.g. ps5, ps4, xbox, atk3. Leave unset to use teleop_twist_joy defaults. - JOY_CONFIG=${JOY_CONFIG:-} # FastDDS profile restricts DDS traffic to a single interface. # Override FASTDDS_INTERFACE in .env or on the command line (e.g. eth0, wlan1). - FASTDDS_DEFAULT_PROFILES_FILE=/fastdds_wifi.xml - FASTDDS_INTERFACE=${FASTDDS_INTERFACE:-wlan0} # Not started by default — run explicitly: # keyboard: docker compose run --rm teleop teleop-keyboard # joystick: docker compose run --rm teleop teleop-joystick profiles: - teleop webui: build: context: webui dockerfile: Dockerfile platforms: - linux/arm64 args: # Hostname of the GStreamer signaling server, baked into the frontend bundle. # Override with: VITE_WEBRTC_HOST=raspbot-v2.local VITE_WEBRTC_HOST: ${VITE_WEBRTC_HOST:-} image: raspbot_v2_webui:latest network_mode: host ipc: host environment: - ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-0} restart: unless-stopped camera_publisher: build: context: ./camera_publisher platforms: - linux/amd64 - linux/arm64 image: ${REGISTRY:-camera-publisher}:${TAG:-latest} restart: unless-stopped network_mode: host ipc: host devices: - /dev/video0:/dev/video0 - /dev/video1:/dev/video1 - /dev/media0:/dev/media0 environment: VIDEO_DEVICE: /dev/video0 WIDTH: 640 HEIGHT: 480 FPS: 30 CAMERA_FORMAT: mjpeg CAMERA_NAMESPACE: /camera FASTDDS_BUILTIN_TRANSPORTS: LARGE_DATA webrtc_streamer: build: context: ./webrtc_streamer platforms: - linux/amd64 - linux/arm64 image: ${REGISTRY:-webrtc-streamer}:${TAG:-latest} restart: unless-stopped network_mode: host ipc: host environment: IMAGE_TOPIC: /camera/image_raw PORT: 8443 BITRATE: 2000000 FASTDDS_BUILTIN_TRANSPORTS: LARGE_DATA