docker-steam-headless icon indicating copy to clipboard operation
docker-steam-headless copied to clipboard

[Bug]: Two Docker one Host - Mouse shared between Dockers

Open Gylfkxjyjdll opened this issue 1 year ago • 13 comments

Describe the Bug

I use two Docker with separated GPUs. The GPU Part works so far very good. But the Problem ist Mouse & Keyboard. If i move the Mouse Docker 1 the mouse moves in Docker2 as well. To be honest, i tried different things but in the end, i dont know where to start to debug. Host ist Debian 11 with a nvidia 4070 ti super and 3090

Same with audio. The audio from Docker1 is on Docker2 and visa versa.

Steps to Reproduce

No response

Expected Behavior

Audio from Docker 1 plays in stream of Docker1 and visa versa

Input from Mouse und Keyboard from Docker1 is containerd in Docker1 and visa versa

Screenshots

No response

Relevant Settings

No response

Version

latest

Platform

xconf.org on the host:


Section "ServerLayout"
    Identifier     "Layout0"
    Screen      0  "Screen0"
    InputDevice    "Keyboard0" "CoreKeyboard"
    InputDevice    "Mouse0" "CorePointer"
    Option         "Xinerama" "0"
EndSection

Section "ServerLayout"
    Identifier     "Layout1"
    Screen      0  "Screen1"
    InputDevice    "Keyboard1" "CoreKeyboard"
    InputDevice    "Mouse1" "CorePointer"
    Option         "Xinerama" "1"
EndSection

Section "Files"
EndSection

Section "InputDevice"
    # generated from default
    Identifier     "Mouse0"
    Driver         "mouse"
    Option         "Protocol" "auto"
    Option         "Device" "/dev/input/mouse0" 
    Option         "Emulate3Buttons" "no"
    Option         "ZAxisMapping" "4 5"
EndSection

Section "InputDevice"
    # generated from default
    Identifier     "Mouse1"
    Driver         "mouse"
    Option         "Device" "/dev/input/mouse2"
    Option         "Protocol" "auto"
    Option         "ZAxisMapping" "4 5"
EndSection


Section "InputDevice"
    # generated from default
    Identifier     "Keyboard0"
    Driver         "kbd"
EndSection

Section "InputDevice"
    # generated from default
    Identifier     "Keyboard1"
    Driver         "kbd"
EndSection


Section "Monitor"
    Identifier     "Monitor0"
    VendorName     "Unknown"
    ModelName      "Unknown"
    Option         "DPMS"
EndSection

Section "Monitor"
    Identifier     "Monitor1"
    VendorName     "Unknown"
    ModelName      "Unknown"
    Option         "DPMS"
EndSection

Section "Device"
    Identifier     "Device0"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BusID          "PCI:1:0:0"
EndSection

Section "Device"
    Identifier     "Device1"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BusID          "PCI:9:0:0"
EndSection

Section "Screen"
    Identifier     "Screen0"
    Device         "Device0"
    Monitor        "Monitor0"
    DefaultDepth    24
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

Section "Screen"
    Identifier     "Screen1"
    Device         "Device1"
    Monitor        "Monitor1"
    DefaultDepth   24
    SubSection     "Display"
        Depth      24
    EndSubSection
EndSection

the compose-file Docker1:



version: "3.8"

services:
  steam-headless:
    image: josh5/steam-headless:latest
    restart: unless-stopped
    shm_size: ${SHM_SIZE}
    #privileged: true
    ipc: host # Could also be set to 'shareable'
    ulimits:
      nofile:
        soft: 1024
        hard: 524288
    cap_add:
      - NET_ADMIN
      - SYS_ADMIN
      - SYS_NICE
    security_opt:
      - seccomp:unconfined
      - apparmor:unconfined


    # NETWORK:
    ## NOTE:  With this configuration, if we do not use the host network, then physical device input
    ##        is not possible and your USB connected controllers will not work in steam games.
    network_mode: host
    hostname: ${NAME}
    extra_hosts:
      - "${NAME}:127.0.0.1"
    
    # ENVIRONMENT:
    ## Read all config variables from the .env file
    environment:
      # System
      - TZ=${TZ}
      - USER_LOCALES=${USER_LOCALES}
      - DISPLAY=${DISPLAY}
      # User
      - PUID=${PUID}
      - PGID=${PGID}
      - UMASK=${UMASK}
      - USER_PASSWORD=${USER_PASSWORD}
      # Mode
      - MODE=${MODE}
      # Web UI
      - WEB_UI_MODE=${WEB_UI_MODE}
      - ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
      - PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
      - NEKO_NAT1TO1=${NEKO_NAT1TO1}
      # Steam
      - ENABLE_STEAM=${ENABLE_STEAM}
      - STEAM_ARGS=${STEAM_ARGS}
      # Sunshine
      - ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
      - SUNSHINE_USER=${SUNSHINE_USER}
      - SUNSHINE_PASS=${SUNSHINE_PASS}
      # Xorg
      - ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
      - FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
      # Nvidia specific config
      - NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
      - NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
      - NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
    runtime: nvidia
    # DEVICES:
    devices:
      # Use the host fuse device [REQUIRED].
      - /dev/fuse
      # Add the host uinput device [REQUIRED].
      - /dev/uinput
      # Add NVIDIA HW accelerated devices [OPTIONAL].
      # Add NVIDIA HW accelerated devices [OPTIONAL].
      # NOTE: If you use the nvidia container toolkit, this is not needed.
      #       Installing the nvidia container toolkit is the recommended method for running this container
      #- /dev/nvidia3
     # - /dev/nvidia0
     # - /dev/nvidia1
     # - /dev/nvidia2
     # - /dev/nvidiactl
     # - /dev/nvidia-modeset
     # - /dev/nvidia-uvm
     # - /dev/nvidia-uvm-tools
     # - /dev/nvidia-caps/nvidia-cap1
     # - /dev/nvidia-caps/nvidia-cap2
     # - /dev/dri/
    # Ensure container access to devices 13:*
      # NOTE: If you use the nvidia container toolkit, this is not needed.
      #       Installing the nvidia container toolkit is the recommended method for running this container
    # GPU PASSTHROUGH
    deploy:
      resources:
        reservations:
          # Enable support for NVIDIA GPUs.
          # 
          # Ref: https://docs.docker.com/compose/gpu-support/#enabling-gpu-access-to-service-containers
          devices:
            - capabilities: [gpu]
              device_ids: ["${NVIDIA_VISIBLE_DEVICES}"]

    device_cgroup_rules:
      - 'c 13:* rmw'

    # VOLUMES:
    volumes:
      # The location of your home directory.
      - ${HOME_DIR}/:/home/default/:rw

      # The location where all games should be installed.
      # This path needs to be set as a library path in Steam after logging in.
      # Otherwise, Steam will store games in the home directory above.
      - ${GAMES_DIR}/:/mnt/games/:rw

      # The Xorg socket.
      - ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw

      # Pulse audio socket.
      - ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw

the .env file Docker1:


NAME=SteamHeadless2
TZ=Pacific/Auckland
USER_LOCALES=en_US.UTF-8 UTF-8
DISPLAY=:1
SHM_SIZE=2G
HOME_DIR=/srv/dev-disk-by-uuid-2ba384f1-3b00-4b0d-8e09-007772e6f1bf/Docker/steamos1/home
SHARED_SOCKETS_DIR=/opt/container-data/steam-headless/sockets
GAMES_DIR=/srv/dev-disk-by-uuid-2ba384f1-3b00-4b0d-8e09-007772e6f1bf/Docker/steamos/games



PUID=1000
PGID=100
UMASK=000
USER_PASSWORD=password

MODE=primary

WEB_UI_MODE=vnc

ENABLE_VNC_AUDIO=false

PORT_NOVNC_WEB=8084

NEKO_NAT1TO1=

ENABLE_STEAM=true

STEAM_ARGS=-silent

ENABLE_SUNSHINE=true
SUNSHINE_USER=admin
SUNSHINE_PASS=admin

ENABLE_EVDEV_INPUTS=true
FORCE_X11_DUMMY_CONFIG=false
NVIDIA_DRIVER_CAPABILITIES=all
NVIDIA_VISIBLE_DEVICES=GPU-4d3a6b72-e370-87f2-721f-428302c1a40d
NVIDIA_DRIVER_VERSION=565.57.01

The docker-compose file Docker 2:


---
version: "3.8"

services:
  steam-headless:
    image: josh5/steam-headless:latest
    restart: unless-stopped
    shm_size: ${SHM_SIZE}
    #privileged: true
    ipc: host # Could also be set to 'shareable'
    ulimits:
      nofile:
        soft: 1024
        hard: 524288
    cap_add:
      - NET_ADMIN
      - SYS_ADMIN
      - SYS_NICE
    security_opt:
      - seccomp:unconfined
      - apparmor:unconfined

    # NETWORK:
    ## NOTE:  With this configuration, if we do not use the host network, then physical device input
    ##        is not possible and your USB connected controllers will not work in steam games.
    network_mode: host
    hostname: ${NAME}
    extra_hosts:
      - "${NAME}:127.0.0.1"
    
    # ENVIRONMENT:
    ## Read all config variables from the .env file
    environment:
      # System
      - TZ=${TZ}
      - USER_LOCALES=${USER_LOCALES}
      - DISPLAY=${DISPLAY}
      # User
      - PUID=${PUID}
      - PGID=${PGID}
      - UMASK=${UMASK}
      - USER_PASSWORD=${USER_PASSWORD}
      # Mode
      - MODE=${MODE}
      # Web UI
      - WEB_UI_MODE=${WEB_UI_MODE}
      - ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
      - PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
      - NEKO_NAT1TO1=${NEKO_NAT1TO1}
      # Steam
      - ENABLE_STEAM=${ENABLE_STEAM}
      - STEAM_ARGS=${STEAM_ARGS}
      # Sunshine
      - ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
      - SUNSHINE_USER=${SUNSHINE_USER}
      - SUNSHINE_PASS=${SUNSHINE_PASS}
      # Xorg
      - ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
      - FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
      # Nvidia specific config
      - NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
      - NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
      - NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
    runtime: nvidia
    # DEVICES:
    devices:
      # Use the host fuse device [REQUIRED].
      - /dev/fuse
      # Add the host uinput device [REQUIRED].
      - /dev/uinput
      # Add NVIDIA HW accelerated devices [OPTIONAL].
      # Add NVIDIA HW accelerated devices [OPTIONAL].
      # NOTE: If you use the nvidia container toolkit, this is not needed.
      #       Installing the nvidia container toolkit is the recommended method for running this container
      #- /dev/nvidia3
     # - /dev/nvidia0
     # - /dev/nvidia1
     # - /dev/nvidia2
     # - /dev/nvidiactl
     # - /dev/nvidia-modeset
     # - /dev/nvidia-uvm
     # - /dev/nvidia-uvm-tools
     # - /dev/nvidia-caps/nvidia-cap1
     # - /dev/nvidia-caps/nvidia-cap2
     # - /dev/dri/
    # Ensure container access to devices 13:*
      # NOTE: If you use the nvidia container toolkit, this is not needed.
      #       Installing the nvidia container toolkit is the recommended method for running this container
    # GPU PASSTHROUGH
    deploy:
      resources:
        reservations:
          # Enable support for NVIDIA GPUs.
          # 
          # Ref: https://docs.docker.com/compose/gpu-support/#enabling-gpu-access-to-service-containers
          devices:
            - capabilities: [gpu]
              device_ids: ["${NVIDIA_VISIBLE_DEVICES}"]

    device_cgroup_rules:
      - 'c 13:* rmw'

    # VOLUMES:
    volumes:
      # The location of your home directory.
      - ${HOME_DIR}/:/home/default/:rw

      # The location where all games should be installed.
      # This path needs to be set as a library path in Steam after logging in.
      # Otherwise, Steam will store games in the home directory above.
      - ${GAMES_DIR}/:/mnt/games/:rw

      # The Xorg socket.
      - ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw

      # Pulse audio socket.
      - ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw

.env file Docker2:

NAME=SteamHeadless2
TZ=Pacific/Auckland
USER_LOCALES=en_US.UTF-8 UTF-8
DISPLAY=:1
SHM_SIZE=2G
HOME_DIR=/srv/dev-disk-by-uuid-2ba384f1-3b00-4b0d-8e09-007772e6f1bf/Docker/steamos1/home

SHARED_SOCKETS_DIR=/opt/container-data/steam-headless/sockets

GAMES_DIR=/srv/dev-disk-by-uuid-2ba384f1-3b00-4b0d-8e09-007772e6f1bf/Docker/steamos/games
 
PUID=1000
PGID=100
UMASK=000
USER_PASSWORD=password

MODE=primary

WEB_UI_MODE=vnc
ENABLE_VNC_AUDIO=false
PORT_NOVNC_WEB=8084
NEKO_NAT1TO1=
STEAM_ARGS=-silent
ENABLE_SUNSHINE=true
SUNSHINE_USER=admin
SUNSHINE_PASS=admin

ENABLE_EVDEV_INPUTS=true
FORCE_X11_DUMMY_CONFIG=false

NVIDIA_DRIVER_CAPABILITIES=all

NVIDIA_VISIBLE_DEVICES=GPU-4d3a6b72-e370-87f2-721f-428302c1a40d

NVIDIA_DRIVER_VERSION=565.57.01


Relevant log output

No response

Gylfkxjyjdll avatar Nov 23 '24 11:11 Gylfkxjyjdll

This is an issue with the current implementation of udev inside the container. Something that one day I hope to look at improving. For now, this is a known limitation.

Josh5 avatar Nov 27 '24 03:11 Josh5

Have you checked out how games-on-whales/wolf handles a fake-udev? That might be an effective solution.

ghost avatar Dec 23 '24 01:12 ghost

This is an issue with the current implementation of udev inside the container. Something that one day I hope to look at improving. For now, this is a known limitation.

I was this close to success... Wanted to host a "virtual" PC for my friend while he is not present at home, so he could play with me. He would be streaming with moonlight from a container, and i would be sitting at the same PC, just on the physical seat. However, yes, as pointed out, sunshine uses uinput, which ruins all of it, because we dont have a separate seat for udev to pass input devices to. Tried to solve it several times to no avail. Method of doing my thing with virtualgl is even worse. I literally nerd-sniped myself for a whole work day, to find out at the end, that it was not worth it. Ugh.

Edit: nevertheless my sobbing, this project is really cool. I had seen amount of work that went into all of the setup. Its nuts. Hats off to you, Josh!

kcalbxof avatar Jul 16 '25 00:07 kcalbxof

I noticed that Sunshine joystick passes to the container fully, i do not see ANY trace of it on the host system, but when i inspect container, i see it as event26 device, which is not present on the host. However, mouse and keyboard still "stick" to the seat, being both on host and container as event6 and event8 devices respectfully.

kcalbxof avatar Jul 16 '25 01:07 kcalbxof

It is possible to make it so that host system would ignore input events from specified devices, leaving them to the container. One could make a patch for the sunshine, which could allow to rename devices that Sunshine uses (at least their product id, for example), in order to allow multiple virtual peripherals to co-exist on one system, which, in turn, would allow multiple remote seats at one rig.

Following udev rules are placed in /lib/udev/rules.d/60-sunshine.rules, it already exists, so i placed it here temporarily. But you certainly should make your own rule in /etc/udev/rules.d/, so that it wont be overwritten.

SUBSYSTEM=="input", ATTRS{id/vendor}=="beef", ATTRS{id/product}=="dead", ATTRS{name}=="Mouse passthrough", ENV{LIBINPUT_IGNORE_DEVICE}="1"
SUBSYSTEM=="input", ATTRS{id/vendor}=="beef", ATTRS{id/product}=="dead", ATTRS{name}=="Keyboard passthrough", ENV{LIBINPUT_IGNORE_DEVICE}="1"

So, yes, in short - i did make it kinda work. Would fully test it later, though.

kcalbxof avatar Jul 16 '25 01:07 kcalbxof

I dont mind building a custom sunshine for steam headless with any needed patches. I'm keen on this becoming a thing where we can play 2 games on one GPU.

Josh5 avatar Jul 16 '25 10:07 Josh5

Unfortunately, i tested it today, and found out that dummy X11 screen does not support DRI3, which is a no-go for vulkan rendering. In that case, llvmpipe is used, which is awfully slow. I mean, i wouldve been fine with even 50% perfomance loss, but 1-2 fps is not it. But this is another issue, which is https://github.com/Steam-Headless/docker-steam-headless/issues/168 Do not know how to proceed further, i have too little experience in X11/Wayland multiseat configurations.

kcalbxof avatar Jul 16 '25 10:07 kcalbxof

@kcalbxof - I've been quietly referencing this thread trying to get two distinct containers running in a fresh Debian install with Docker, a single GPU, and Xorg running on the host.

I suspect using a dummy plug will enable support for DRI3 within the container, since it does not have to create a dummy X11 screen, I'll report back if it works.

https://www.amazon.com/FUERAN-Emulator-Headless-Supports-3840x2160/dp/B0D4Z7MR9G

cwilby avatar Oct 19 '25 20:10 cwilby

@cwilby i actually have two of those plugs, but i trashed whole docker setup due to having to clean up the disk. Might get back to this a bit later.

kcalbxof avatar Oct 19 '25 20:10 kcalbxof

@kcalbxof - I've been quietly referencing this thread trying to get two distinct containers running in a fresh Debian install with Docker, a single GPU, and Xorg running on the host.

I suspect using a dummy plug will enable support for DRI3 within the container, since it does not have to create a dummy X11 screen, I'll report back if it works.

https://www.amazon.com/FUERAN-Emulator-Headless-Supports-3840x2160/dp/B0D4Z7MR9G

Steam‑Headless is a great project, but for a multi‑user game platform /parallel game-streamingI strongly recommend using games-on-whales. l

Gylfkxjyjdll avatar Oct 23 '25 08:10 Gylfkxjyjdll

Bear with me for I am but a slightly evolved monkey with access to technology..

Following on from what others have said here:

  • Games on Whales is built on Wolf.
  • Wolf is a wrapper(?) around Sunshine
  • Wolf adds fakeudev (as a ghost user mentioned).
  • Their fakeudev implementation creates a socket for each session here
  • Our dumbudev implementation relays kernel events through bind mounting(?)

Perhaps dumbudev can be modified or swapped for fakeudev given it's MIT licensing?

cwilby avatar Oct 28 '25 20:10 cwilby

Bear with me for I am but a slightly evolved monkey with access to technology..

Following on from what others have said here:

  • Games on Whales is built on Wolf.
  • Wolf is a wrapper(?) around Sunshine
  • Wolf adds fakeudev (as a ghost user mentioned).
  • Their fakeudev implementation creates a socket for each session here
  • Our dumbudev implementation relays kernel events through bind mounting(?)

Perhaps dumbudev can be modified or swapped for fakeudev given it's MIT licensing?

Wolf is not a sunshine wrapper. It is a complete ground up replacement. Wolf has full control over IO in a container with fakeudev. The fakeudev is for faking udev stuff to apps from wolf, it does not do anything with the kenel messages as far as I am aware. My dumbudev listens for real kernel messages and relays them to the unprivileged container.

It is possible to have sunshine manage input without udev and uinput, but we would need to patch it, and I have not currently got the time.

Josh5 avatar Oct 28 '25 21:10 Josh5

@Josh5 Thanks for taking the time to explain 👍

cwilby avatar Oct 30 '25 00:10 cwilby