25

Environment

  • Host running Ubuntu 14.04.5 LTS
  • Docker version 17.09.0-ce, build afdb6d4
  • Chromium 62.0.3202.89
  • 2 webcams: /dev/video0, /dev/video1

Cameras

# v4l2-ctl --list-devices
Venus USB2.0 Camera (usb-0000:00:1a.0-1.2.2):
    /dev/video1

USB 2.0 Camera (usb-0000:00:1a.0-1.3):
    /dev/video0

I need to share the webcams on Ubuntu 14.04 host to the Ubuntu 16.04 docker container and be able to get the video streams (WebRTC getUserMedia) from each camera on each chromium instance respectively running on the host and the container or on 2 separate docker containers.

To test the getUserMedia, I am browsing to


How to reproduce

Dockerfile

FROM ubuntu:16.04

# Install chromium
RUN apt-get update \
    && apt-get install sudo chromium-browser alsa-base alsa-utils alsa-oss -y \
    && rm -rf /var/lib/apt/lists/*

# Create a normal user to run chromium as
RUN useradd --create-home browser \
    && adduser browser video \
    && adduser browser audio \
    && usermod -aG sudo browser
USER browser
WORKDIR /home/browser

ENTRYPOINT ["/usr/bin/chromium-browser", "--use-fake-ui-for-media-stream", "--disable-infobars", "--allow-running-insecure-content", "--ignore-certificate-errors"]
CMD ["https://www.stackoverflow.com/"]

docker-compose up

$ more docker-compose.yml 
version: '3'
services:
  chromium_video1:
    build:
      context: .
      dockerfile: Dockerfile
    image: ubuntu-cr:0.1
#    privileged: true # then you don't need the devices section

    # Pass the URL as an argument (CMD) to ENTRYPOINT in the Dockerfile
    #command: ["https://www.onlinemictest.com/webcam-test/"] # WORKS
    command: ["https://webrtc.github.io/samples/src/content/getusermedia/gum/"] # FAILS

    environment:
        #DISPLAY: $DISPLAY
        DISPLAY:
        XAUTHORITY: /.Xauthority

    devices:
        - /dev/video1
        - /dev/dri
#        - /dev/snd

    volumes:
        - /tmp/.X11-unix:/tmp/.X11-unix
        - ~/.Xauthority:/.Xauthority:ro
        - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket

    cap_add:
        - SYS_ADMIN

  chromium_video0:
    build:
      context: .
      dockerfile: Dockerfile
    image: ubuntu-cr:0.1
#    privileged: true

    # Pass the URL as an argument (CMD) to ENTRYPOINT in the Dockerfile
    #command: ["https://www.onlinemictest.com/webcam-test/"]
    command: ["https://webrtc.github.io/samples/src/content/getusermedia/gum/"]

    environment:
        DISPLAY:
        XAUTHORITY: /.Xauthority

    devices:
        - /dev/video0
        - /dev/dri
#        - /dev/snd

    volumes:
        - /tmp/.X11-unix:/tmp/.X11-unix
        - ~/.Xauthority:/.Xauthority:ro
        - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket

    cap_add:
        - SYS_ADMIN

Additional tries with

command: ["https://appear.in/hello"]

and

command: ["https://test.webrtc.org/"]

leads to the same thing, once one cam starts streaming the other can't

Start Chromium in docker containers

export DISPLAY=:0.0 
docker-compose up

RESULTS

Using https://webrtc.github.io/samples/src/content/getusermedia/gum/ => FAILS

https://webrtc.github.io/samples/src/content/getusermedia/gum/ FAILS:(

if I close chromium_video1, then chromium_video0 streams video after a browser refresh (?).

Tried getUserMedia from the web console:

 navigator.mediaDevices.getUserMedia({audio: true, video: true})

GUM Not Readable error

but after closing chromium streaming /dev/video1, now /dev/video0 is readable. The getUserMedia command resolves and the camera streams video from /dev/video0

GUM resolved after closing the streaming Chromium

GUM resolved

They are not accessing the same device. I checked in chrome://media-internals

chrome://media-internals

Using https://www.onlinemictest.com/webcam-test/ WORKS!!!!!?!?!?!

When using https://www.onlinemictest.com/webcam-test/ instead, it works, we can see streams for both cams. I believe that particular site is still using URL.createObjectURL.

https://www.onlinemictest.com/webcam-test/ WORKS?!

images

docker images
REPOSITORY      TAG            IMAGE ID            CREATED             SIZE
ubuntu-cr       0.1            a61f5506b1f9        9 minutes ago       764MB
ubuntu          16.04          747cb2d60bbe        2 months ago        122MB

Open a Chromium browser to the same URL on the host

:( I get the ERROR message

NotReadableError

Any pointers on how to configure my docker container to allow one cam to be assigned to the host while the other is dedicated to the docker container?

Interesting threads

  • NotReadableError: Failed to allocate videosource points that this may be happening because the camera is used by another application.

  • Interestingly, when I open 2 Chromium instances on the host (no container this time) pointing to the same camera test page (getUserMedia), it does manage to get the same video stream to the 2 Chromium instances. That's when I try to access from a container that it conflicts. It can play either one or the other, but not at the same time. So it could be something to configure on the docker container. Still, tring to understand why this is happening.

UPDATE

docker logs

chromium_video1  | libGL error: failed to open drm device: No such file or directory
chromium_video1  | libGL error: failed to load driver: i965
chromium_video0  | libGL error: failed to open drm device: No such file or directory
chromium_video0  | libGL error: failed to load driver: i965

Resolved this one reading this thread

Tried to share devices as suggested in the comments below, to no avail

- /dev/video1:/dev/video1:rm 
- /dev/video1:/dev/video1:r  
- /dev/video1:/dev/video1:rw

Questions

  • What happens when a camera gets accessed and starts streaming? is there a lock file created and where? Note however that I am not accessing the same camera.

On the volumes sections I am sharing

- /tmp/.X11-unix:/tmp/.X11-unix
- ~/.Xauthority:/.Xauthority:ro
- /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket

I don't think these files are the problem, but still investigating

zabumba
  • 12,001
  • 11
  • 58
  • 117
  • Have you tried mounting whole `/dev` in the container? – emix Dec 21 '17 at 09:36
  • how do you do that? I have used `privileged` option, which is the equivalent. you can try by yourself using my `Dockerfile` and `docker-compose.xml`. You will see that once the container is up, `/dev` is accessible ... right? – zabumba Dec 21 '17 at 11:08
  • I meant by adding the `/dev:/dev:ro` to the volume definition of the container. – emix Dec 21 '17 at 12:41
  • Thanks. I will give it a try, but is there any pragmatic on doing so? – zabumba Dec 21 '17 at 13:46
  • To be honest idk :) The question was how to share devices between the host and a container. – emix Dec 21 '17 at 14:43
  • I see the confusion. I did elaborate. I will try to reformulate the tittle to be more compelling. if you have a linux box, you will be able to reproduce my issue but running a docker container just like I have described. I can share, but I cannot have both browser accessing the same device when one Chromium is trying to access from a container – zabumba Dec 22 '17 at 11:24
  • @zabumba, your test on the host should launch two chromes with different profiles. Because you want to make sure when they are two different processes/profile the camera is accessible to both and debug the container part – Tarun Lalwani Dec 27 '17 at 14:03
  • @TarunLalwani I read and reread you a dozen times. I don't understand what to make of your comment. You may want to be more specific if you actually think you know what is happening ... I know that you are trying to help, but I don't understand your pointer. thanks anyway – zabumba Jan 08 '18 at 22:37
  • 3
    @zabumba, can you try using `- /dev/video1:/dev/video1:rm` or `- /dev/video1:/dev/video1:r` or `- /dev/video1:/dev/video1:rw` and see if that helps in anyway? I think what might be happening is the exclusivity of device being attached to the container – Tarun Lalwani May 15 '18 at 07:16
  • @TarunLalwani that didn't resolved, but thank you for the suggestion. – zabumba May 15 '18 at 20:16
  • 1
    [This](https://stackoverflow.com/a/34472148/3425640) answer might help – trust512 May 15 '18 at 22:21
  • This is the part when you need to *strace* the process. – Robert May 16 '18 at 09:32
  • There must be a lock file created on the host, but can't guess why it should affect a totally different device. – zabumba May 16 '18 at 15:13
  • @Robert I wouldn't know how to use `strace` to debug my problem, but thanks for the suggestion – zabumba May 16 '18 at 15:28
  • Another interesting thing, is that it actually streams from boths cams when using https://www.onlinemictest.com/webcam-test/ ... that might be a WebRTC thingy after all. Something about how `getUserMedia` is utilized. – zabumba May 16 '18 at 20:36
  • 1
    @zabumba, i think you should open an issue with docker. What might be happening here is that the device is locked with docker and it doesn't let it share with other things. This may be a bug (as per you) and a limitation (as per docker) – Tarun Lalwani May 22 '18 at 05:17

1 Answers1

1

If you just want separate Chrome sessions you can simply start it with:

chromium-browser --user-data-dir=/tmp/chrome1 

and another instance with

chromium-browser --user-data-dir=/tmp/chrome2

Docker is just a way to document and repeat setting up of a very specific environment. The additional layer of security that it adds in minimal, especially with the extra permissions you're passing on and especially in comparison to Chrome's really well tested security.

If you need a bit more isolation, you can create separate users:

 # run these lines individualy, just press Enter for everything, don't set passwords for them, they won't be able to log in. 
 sudo adduser chrome1
 sudo adduser chrome2 

 # if you want to give each access to only one of the cams you can try this
 sudo chown chrome1:chrome1 /dev/video0 
 sudo chown chrome2:chrome2 /dev/video1
 # keeping in mind unplugging and replugging the camera might reset the permissions unless you update the relevant /etc files

 # to allow anyone to use your X
 xhost +

 # run the two separate browsers
 sudo su - chrome1 -c chromium-browser & 
 sudo su - chrome2 -c chromium-browser &
dagelf
  • 1,016
  • 1
  • 8
  • 16
  • I need `/dev/video0` cam available on one chromium and `/dev/video1` cam on the other chromium BUT I don't want both instances of chromium to have access to both cams. – zabumba Jun 27 '18 at 15:42
  • I don't understand. `adduser` to what and for what purpose? thx anyway – zabumba Jun 27 '18 at 16:51
  • 1
    Sorry I clicked by accident Have you tried something like: sudo adduser -D chrome1; sudo adduser -D chrome2; sudo chown chrome1:chrome1 /dev/video0; sudo chown chrome2:chrome2 /dev/video1; sudo su - chrome1 -c chromium-browser & sudo su - chrome2 -c chromium-browser – dagelf Jun 27 '18 at 17:10
  • ok creating 2 users and set permissions on `/dev/videoX` accordingly. Yes! interesting idea! I will try. You may edit your answer too. – zabumba Jun 27 '18 at 17:22
  • you would have to precede that with xhost + – dagelf Jun 27 '18 at 17:57
  • cameras may be unplugged, most importantly I need them to really to match exactly their respective users, cause they will have different roles in my setup. I will award you a bounty soon. thx – zabumba Jun 27 '18 at 19:50
  • 1
    If they are going to get unplugged, and you want them to have the right permissions when you plug them back in, assuming you're on Ubuntu or Debian or Arch - you'll have to create a file like here: https://wiki.archlinux.org/index.php/udev#Video_device - ie. KERNEL=="video0", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam1", OWNER="chrome1", GROUP="chrome1" (append OWNER and GROUP) and change the second line too... you can get the vendor and product id's from "dmesg" after plugging in respective devices, or from /sys – dagelf Jun 28 '18 at 08:08
  • Yes I had created my `/etc/udev/rules.d/myproject.rules` rules, but didn't realise I could add `GROUP` and `OWNER`. This is excellent. Will try now. You may as edit your answer accordingly to make it more complete. I think this is helpful for others. Cheers – zabumba Jun 28 '18 at 20:46
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/173992/discussion-between-zabumba-and-dagelf). – zabumba Jun 28 '18 at 22:41