L'ultima volta che ho verificato, Docker non aveva alcun mezzo per fornire l'accesso del contenitore alla porta seriale o USB dell'host . C'è un trucco che permette di farlo?
L'ultima volta che ho verificato, Docker non aveva alcun mezzo per fornire l'accesso del contenitore alla porta seriale o USB dell'host . C'è un trucco che permette di farlo?
Risposte:
Ci sono un paio di opzioni. Puoi usare il --device
flag che puoi usare per accedere ai dispositivi USB senza --privileged
modalità:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
In alternativa, supponendo che il dispositivo USB sia disponibile con driver funzionanti, ecc. Sull'host /dev/bus/usb
, è possibile montarlo nel contenitore utilizzando la modalità privilegiata e l' opzione dei volumi . Per esempio:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Si noti che, come suggerisce il nome, non --privileged
è sicuro e deve essere gestito con cura.
Con le versioni attuali di Docker, è possibile utilizzare la --device
bandiera per ottenere ciò che si desidera, senza la necessità di consentire l'accesso a tutti i dispositivi USB.
Ad esempio, se si desidera rendere /dev/ttyUSB0
accessibile solo all'interno del contenitore Docker, è possibile fare qualcosa del tipo:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
--device
flag, come posso determinare qual /dev/<device>
è il dispositivo Android associato sul computer host, specialmente quando utilizzo Docker Quickstart Terminal (VirtualBox Host) per Windows o Mac?
--device
funziona fino a quando il dispositivo USB non viene scollegato / ricollegato e quindi smette di funzionare. Devi usare i dispositivi di cgroup. Ammetterlo .
Potresti semplicemente usare -v /dev:/dev
ma non è sicuro in quanto mappa tutti i dispositivi dal tuo host al contenitore, inclusi i dispositivi a disco grezzo e così via. Fondamentalmente questo consente al container di ottenere il root sull'host, che di solito non è quello che vuoi.
L'uso dell'approccio cgroups è migliore sotto questo aspetto e funziona su dispositivi che vengono aggiunti dopo l'avvio del contenitore.
Vedi i dettagli qui: Accesso ai dispositivi USB in Docker senza usare --privileged
È un po 'difficile da incollare, ma in poche parole, devi ottenere il numero principale per il tuo dispositivo personaggio e inviarlo al cgroup:
189 è il numero maggiore di / dev / ttyUSB *, che puoi ottenere con 'ls -l'. Potrebbe essere diverso sul tuo sistema rispetto al mio:
root@server:~# echo 'c 189:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allow
(A contains the docker containerID)
Quindi avviare il contenitore in questo modo:
docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash debian:amd64
senza fare ciò, qualsiasi dispositivo appena collegato o riavviato dopo l'avvio del contenitore, otterrà un nuovo ID bus e non gli sarà consentito l'accesso nel contenitore.
189
deve essere sostituito. Una descrizione di cosa inviare devices.allow
è disponibile qui: kernel.org/doc/Documentation/cgroup-v1/devices.txt
Volevo estendere le risposte già fornite per includere il supporto per i dispositivi connessi dinamicamente che non sono stati acquisiti /dev/bus/usb
e come farlo funzionare quando si utilizza un host Windows insieme alla VM boot2docker.
Se lavori con Windows, dovrai aggiungere eventuali regole USB per i dispositivi a cui vuoi accedere a Docker nel gestore VirtualBox. Per fare ciò è possibile arrestare la VM eseguendo:
host:~$ docker-machine stop default
Apri VirtualBox Manager e aggiungi il supporto USB con i filtri come richiesto.
Avviare la VM boot2docker:
host:~$ docker-machine start default
Poiché i dispositivi USB sono collegati alla VM boot2docker, i comandi devono essere eseguiti da quella macchina. Apri un terminale con la VM ed esegui il comando Esegui finestra mobile:
host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash
Nota, quando il comando viene eseguito in questo modo, verranno acquisiti solo i dispositivi USB precedentemente collegati. Il flag dei volumi è richiesto solo se si desidera che funzioni con i dispositivi collegati dopo l'avvio del contenitore. In tal caso, puoi utilizzare:
docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash
Nota, ho dovuto usare /dev
invece che /dev/bus/usb
in alcuni casi per catturare un dispositivo simile /dev/sg2
. Posso solo supporre che lo stesso sarebbe vero per dispositivi come /dev/ttyACM0
o /dev/ttyUSB0
.
I comandi di esecuzione docker funzioneranno anche con un host Linux.
Un'altra opzione è quella di regolare udev, che controlla come sono montati i dispositivi e con quali privilegi. Utile per consentire l'accesso non root ai dispositivi seriali. Se hai dispositivi permanentemente collegati, l' --device
opzione è il modo migliore per andare. Se hai dispositivi effimeri, ecco cosa ho usato:
Per impostazione predefinita, i dispositivi seriali sono montati in modo che solo gli utenti root possano accedere al dispositivo. Dobbiamo aggiungere una regola udev per renderli leggibili dagli utenti non root.
Crea un file chiamato /etc/udev/rules.d/99-serial.rules. Aggiungi la seguente riga a quel file:
KERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE = "0666" fornirà a tutti gli utenti autorizzazioni di lettura / scrittura (ma non di esecuzione) per i tuoi dispositivi ttyUSB. Questa è l'opzione più permissiva e potresti voler restringere ulteriormente a seconda delle tue esigenze di sicurezza. Puoi leggere su udev per saperne di più sul controllo di ciò che accade quando un dispositivo è collegato a un gateway Linux.
I dispositivi seriali sono spesso effimeri (possono essere collegati e scollegati in qualsiasi momento). Per questo motivo, non possiamo montare nel dispositivo diretto o nella cartella / dev / serial, perché possono scomparire quando le cose sono scollegate. Anche se li ricolleghi e il dispositivo si presenta di nuovo, tecnicamente è un file diverso da quello che è stato montato, quindi Docker non lo vedrà. Per questo motivo, montiamo l'intera cartella / dev dall'host al contenitore. È possibile farlo aggiungendo il seguente comando di volume al comando di esecuzione Docker:
-v /dev:/dev
Se il tuo dispositivo è collegato in modo permanente, utilizzare l'opzione --device o un montaggio di volume più specifico è probabilmente un'opzione migliore dal punto di vista della sicurezza.
Se non hai usato l'opzione --device e montato nell'intera cartella / dev, ti verrà richiesto di eseguire il contenitore in modalità privilegiata (vado a controllare le cose del cgroup sopra menzionate per vedere se questo può essere rimosso ). È possibile farlo aggiungendo quanto segue al comando di esecuzione Docker:
--privileged
Se il dispositivo può essere collegato e scollegato, Linux non garantisce che verrà sempre montato nella stessa posizione ttyUSBxxx (specialmente se si dispone di più dispositivi). Fortunatamente, Linux creerà automaticamente un collegamento simbolico al dispositivo nella cartella / dev / serial / by-id. Il file in questa cartella sarà sempre chiamato lo stesso.
Questa è la carrellata, ho un articolo sul blog che approfondisce i dettagli.
È difficile per noi associare un dispositivo USB specifico a un contenitore docker che è anche specifico. Come puoi vedere, il modo consigliato per raggiungere è:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Legherà tutti i dispositivi a questo contenitore. Non è sicuro. A tutti i container è stato concesso di gestirli tutti.
Un altro modo è legare i dispositivi con devpath. Potrebbe apparire come:
docker run -t -i --privileged -v /dev/bus/usb/001/002:/dev/bus/usb/001/002 ubuntu bash
o --device
(meglio, no privileged
):
docker run -t -i --device /dev/bus/usb/001/002 ubuntu bash
Molto più sicuro. Ma in realtà è difficile sapere qual è il devpath di un dispositivo specifico.
Ho scritto questo repository per risolvere questo problema.
https://github.com/williamfzc/usb2container
Dopo aver distribuito questo server, è possibile ottenere facilmente tutte le informazioni dei dispositivi collegati tramite richiesta HTTP:
curl 127.0.0.1:9410/api/device
e prendi:
{
"/devices/pci0000:00/0000:00:14.0/usb1/1-13": {
"ACTION": "add",
"DEVPATH": "/devices/pci0000:00/0000:00:14.0/usb1/1-13",
"DEVTYPE": "usb_device",
"DRIVER": "usb",
"ID_BUS": "usb",
"ID_FOR_SEAT": "xxxxx",
"ID_MODEL": "xxxxx",
"ID_MODEL_ID": "xxxxx",
"ID_PATH": "xxxxx",
"ID_PATH_TAG": "xxxxx",
"ID_REVISION": "xxxxx",
"ID_SERIAL": "xxxxx",
"ID_SERIAL_SHORT": "xxxxx",
"ID_USB_INTERFACES": "xxxxx",
"ID_VENDOR": "xxxxx",
"ID_VENDOR_ENC": "xxxxx",
"ID_VENDOR_FROM_DATABASE": "",
"ID_VENDOR_ID": "xxxxx",
"INTERFACE": "",
"MAJOR": "189",
"MINOR": "119",
"MODALIAS": "",
"PRODUCT": "xxxxx",
"SEQNUM": "xxxxx",
"SUBSYSTEM": "usb",
"TAGS": "",
"TYPE": "0/0/0",
"USEC_INITIALIZED": "xxxxx",
"adb_user": "",
"_empty": false,
"DEVNAME": "/dev/bus/usb/001/120",
"BUSNUM": "001",
"DEVNUM": "120",
"ID_MODEL_ENC": "xxxxx"
},
...
}
e legali ai tuoi contenitori. Ad esempio, puoi vedere il DEVNAME di questo dispositivo è /dev/bus/usb/001/120
:
docker run -t -i --device /dev/bus/usb/001/120 ubuntu bash
Forse aiuterà.
Con le ultime versioni della finestra mobile, questo è sufficiente:
docker run -ti --privileged ubuntu bash
Darà accesso a tutte le risorse di sistema (in / dev per esempio)
Aggiungendo alle risposte sopra, per coloro che desiderano un modo rapido per utilizzare un dispositivo USB esterno (HDD, unità flash) che lavora all'interno della docker e non utilizza la modalità privilegiata:
Trova il devpath sul tuo dispositivo sull'host:
sudo fdisk -l
È possibile riconoscere l'unità in base alla sua capacità abbastanza facilmente dall'elenco. Copia questo percorso (per l'esempio che segue /dev/sda2
).
Disque /dev/sda2 : 554,5 Go, 57151488 octets, 111624 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Montare questo devpath (preferibile a /media
):
sudo mount <drive path> /media/<mount folder name>
Puoi quindi usarlo come parametro per docker run
piacere:
docker run -it -v /media/<mount folder name>:/media/<mount folder name>
o nella finestra mobile comporre sotto i volumi:
services:
whatevermyserviceis:
volumes:
- /media/<mount folder name>:/media/<mount folder name>
E ora quando corri ed entri nel tuo contenitore, dovresti essere in grado di accedere all'unità all'interno del contenitore in /media/<mount folder name>
NOTA BENE:
Se si desidera accedere dinamicamente ai dispositivi USB che possono essere collegati mentre il contenitore docker è già in esecuzione, ad esempio accedere a una webcam USB appena collegata su / dev / video0, è possibile aggiungere una regola cgroup all'avvio del contenitore. Questa opzione non ha bisogno di un contenitore --privileged e consente solo l'accesso a tipi specifici di hardware.
Controlla il numero principale del dispositivo del tipo di dispositivo che desideri aggiungere. Puoi cercarlo nella documentazione del kernel linux . Oppure puoi controllarlo per il tuo dispositivo. Ad esempio, per controllare il numero principale del dispositivo per una webcam collegata a / dev / video0, è possibile eseguire una ls -la /dev/video0
. Ciò si traduce in qualcosa di simile:
crw-rw----+ 1 root video 81, 0 Jul 6 10:22 /dev/video0
Dove il primo numero (81) è il numero principale del dispositivo. Alcuni numeri principali dei dispositivi comuni:
Aggiungi regole all'avvio del contenitore finestra mobile:
--device-cgroup-rule='c major_number:* rmw'
regola per ogni tipo di dispositivo a cui desideri accedere-v /run/udev:/run/udev:ro
-v /dev:/dev
Quindi, per aggiungere tutte le webcam USB e i dispositivi serial2usb al contenitore della finestra mobile, eseguire:
docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash