2015-12-16 16 views
14

Ho bisogno di condividere dispositivi specifici da /dev sulla mia macchina Linux host con i miei contenitori docker.Condivisione di dispositivi (webcam, unità USB, ecc.) Con Docker

I --privileged opere bandiera per condividere tutti i dispositivi in ​​/dev che sono presenti al momento docker run viene chiamato, ma qualsiasi dispositivo successivamente aggiunti o rimossi non propagano nel contenitore.

Ho provato docker run -v=/dev:/dev ... ma questo ha finito per rovinare le autorizzazioni e la proprietà di file come/dev/pts, portando alla macchina host a non essere in grado di creare nuovi psuedo-terminali.

Ho anche provato il flag --device, ma ciò non consente di condividere un dispositivo che non esiste ancora.

Infine, ho provato la condivisione di volumi per dispositivi come -v=/dev/video0:/dev/video0 ma se/dev/video0 non esiste prima della corsa, finestra mobile crea una directory lì e una webcam non prenderà/dev/video0 quando collegato.

C'è un modo migliore per ottenere questa funzionalità supportata?

risposta

6

Cercate controllare il flag --device

--device=[] 
     Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm) 

Have a nice day!

+0

Il problema con il flag --device è che non riesce se il dispositivo non è già presente. Ho una configurazione piuttosto complicata in cui 4 webcam USB e 4 schede SD sono regolarmente collegate/scollegate da un server e alcune app Docker si collegano alle webcam e salvano i dati sulle schede. – Ryan

+0

Oh, capisco. Questo è davvero piuttosto complicato e non sono sicuro che Docker abbia già risolto questo tipo di situazioni. L'unico consiglio che posso darti è di semplificarlo se mai è possibile, ma potrebbe non adattarsi agli altri tuoi vincoli. – Auzias

7

Penso che in teoria questo sia possibile utilizzando il flag --privileged, in quanto questa cosa ti dà la possibilità di accedere a tutti i dispositivi degli host. Se si installa usbutils o simile (a seconda della distribuzione delle immagini), si vedrà che il contenitore privilegiato è in grado di vedere i dispositivi hotplugged quando è in esecuzione lsusb. Sfortunatamente anche se non appaiono sotto/dev. Scripting la creazione di quei descrittori e farli correttamente gestire dal tuo software sotto/dev può diventare abbastanza coinvolto purtroppo. Tuttavia, non deve essere così per i tuoi dispositivi.

Quello che puoi fare come primo tentativo è semplicemente crearli usando mknod. Ho provato questo con il mio telefono HTC ed è una sorta di funzionato (i dettagli non rilevanti qui), è sufficiente controllare la linea per il dispositivo inserite a caldo in lsusb:

Bus 003 Device 002: ID 0bb4:0f25 HTC (High Tech Computer Corp.) One M8 

passare alla cartella corretta per il descrittore:

cd /dev/bus/usb/003 

controllo la versione principale per il driver USB nel proprio kernel dai descrittori esistenti:

[email protected]:/dev/bus/usb/003# ls -la 
total 0 
drwxr-xr-x 2 root root  160 Dec 26 13:40 . 
drwxr-xr-x 6 root root  120 Dec 26 13:30 .. 
crw-rw-r-- 1 root root 189, 256 Dec 26 13:30 001 
crw-rw-r-- 1 root root 189, 258 Dec 26 13:30 003 
crw-rw-r-- 1 root root 189, 259 Dec 26 13:30 004 
crw-rw-r-- 1 root root 189, 260 Dec 26 13:30 005 
crw-rw-r-- 1 root root 189, 261 Dec 26 13:30 006 

=> 189 :) => creare il cenno del capo e, mentre facendo usa versione minore 0.

mknod 002 c 189 0 

=> almeno lsusb -v è ora in grado di aprire il dispositivo. Lo stesso dovrebbe funzionare per la maggior parte dell'hardware, con alcune eccezioni.

Cosa si potrebbe fare come alternativa, sebbene possibilmente più lento ma sicuramente più sicuro e più nello spirito di Docker e containerizzazione è utilizzare i contenitori per accedere ai dispositivi quando li si monta a caldo e quindi condividere i dispositivi con il contenitore principale eseguendo la tua app video tramite socat tty tramite tcp.

Diciamo hotplug/dev/video0 sull'host, è possibile avviare un nuovo contenitore con questo dispositivo montato in quell'evento. Questo contenitore (che ha socat installata) potrebbe funzionare:

socat tcp-l:54321,reuseaddr,fork file:/dev/video0,nonblock,waitlock=/var/run/video0.lock 

Assumendo questa cosa ha la video0 server host è possibile ora creare il descrittore per video0 sul client tramite:

socat pty,link=/dev/video0,waitslave tcp:video0-server:54321 

Ora si dovrebbe essere in grado di utilizzare il dispositivo bene. Per molti dispositivi, l'overhead di Socat non dovrebbe essere un problema, penso. Se lo script tramite più contenitori che comunicano dinamicamente con il contenitore principale tramite la rete è un'opzione e le prestazioni non sono influenzate in alcun modo dal sovraccarico, quest'ultima opzione è più pulita e più sicura della modalità --privileged secondo me.

+0

Fantastico - dovrò provarlo! Sembra molto promettente. – Ryan

+0

Perché non usare semplicemente il flag '--device'? – Auzias

+1

@Auzias perché la persona ha richiesto una soluzione che consentisse di collegare i dispositivi in ​​un contenitore già in esecuzione. '--device' non ti aiuterà in questo scenario :) –

0

È difficile posizionare il dispositivo quando il sistema è in esecuzione (rilevamento USB), è necessario creare uno script per posizionare i dispositivi così come sono trovati e fare il comando --rm (così ogni volta che si esce dalla macchina viene rimosso, e hai una nuova possibilità di importare i dispositivi)

Problemi correlati