La última vez que lo verifiqué, Docker no tenía ningún medio para dar acceso al contenedor al puerto serie o USB del host . ¿Hay algún truco que permita hacer eso?
La última vez que lo verifiqué, Docker no tenía ningún medio para dar acceso al contenedor al puerto serie o USB del host . ¿Hay algún truco que permita hacer eso?
Respuestas:
Hay un par de opciones. Puede usar el --deviceindicador que puede usar para acceder a dispositivos USB sin --privilegedmodo:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
Alternativamente, suponiendo que su dispositivo USB esté disponible con controladores funcionando, etc. en el host /dev/bus/usb, puede montarlo en el contenedor utilizando el modo privilegiado y la opción de volúmenes . Por ejemplo:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Tenga en cuenta que, como su nombre lo indica, --privilegedes inseguro y debe manejarse con cuidado.
Con las versiones actuales de Docker, puede usar la --devicebandera para lograr lo que desea, sin necesidad de dar acceso a todos los dispositivos USB.
Por ejemplo, si desea que solo sea /dev/ttyUSB0accesible dentro de su contenedor Docker, puede hacer algo como:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
--devicebandera, ¿cómo determino cuál /dev/<device>es el dispositivo Android asociado en la máquina host, especialmente cuando uso Docker Quickstart Terminal (VirtualBox Host) para Windows o Mac?
--devicefunciona hasta que su dispositivo USB se desenchufe / vuelva a enchufar y luego deje de funcionar. Tienes que usar dispositivos cgroup. Para evitarlo .
Podría usarlo, -v /dev:/devpero eso no es seguro, ya que asigna todos los dispositivos desde su host al contenedor, incluidos los dispositivos de disco sin formato, etc. Básicamente, esto permite que el contenedor obtenga root en el host, que generalmente no es lo que desea.
El uso del enfoque cgroups es mejor en ese sentido y funciona en dispositivos que se agregan después del contenedor como se inició.
Vea los detalles aquí: Acceso a dispositivos USB en Docker sin usar --privileged
Es un poco difícil de pegar, pero en pocas palabras, debes obtener el número principal de tu dispositivo de personaje y enviarlo a cgroup:
189 es el número principal de / dev / ttyUSB *, que puede obtener con 'ls -l'. Puede ser diferente en su sistema que en el mío:
root@server:~# echo 'c 189:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allow
(A contains the docker containerID)
Luego, inicie su contenedor de esta manera:
docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash debian:amd64
sin hacer esto, cualquier dispositivo que se haya enchufado o reiniciado nuevamente después de que se inicie el contenedor, obtendrá una nueva ID de bus y no se permitirá el acceso al contenedor.
189debe reemplazarse. devices.allowPuede encontrar una descripción de qué enviar aquí: kernel.org/doc/Documentation/cgroup-v1/devices.txt
Quería extender las respuestas ya dadas para incluir soporte para dispositivos conectados dinámicamente que no se capturan /dev/bus/usby cómo hacer que esto funcione cuando se usa un host de Windows junto con la máquina virtual boot2docker.
Si está trabajando con Windows, deberá agregar cualquier regla USB para los dispositivos a los que desea que Docker acceda dentro del administrador de VirtualBox. Para hacer esto, puede detener la VM ejecutando:
host:~$ docker-machine stop default
Abra el VirtualBox Manager y agregue soporte USB con filtros según sea necesario.
Inicie la máquina virtual boot2docker:
host:~$ docker-machine start default
Dado que los dispositivos USB están conectados a la máquina virtual boot2docker, los comandos deben ejecutarse desde esa máquina. Abra una terminal con la VM y ejecute el comando docker run:
host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash
Tenga en cuenta que cuando el comando se ejecuta de esta manera, solo se capturarán los dispositivos USB conectados anteriormente. El indicador de volúmenes solo es necesario si desea que esto funcione con dispositivos conectados después de que se inicie el contenedor. En ese caso, puede usar:
docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash
Tenga en cuenta que tuve que usar en /devlugar de /dev/bus/usben algunos casos para capturar un dispositivo como /dev/sg2. Solo puedo suponer que lo mismo sería cierto para dispositivos como /dev/ttyACM0o /dev/ttyUSB0.
Los comandos de ejecución de Docker también funcionarán con un host Linux.
Otra opción es ajustar udev, que controla cómo se montan los dispositivos y con qué privilegios. Útil para permitir el acceso no root a dispositivos seriales. Si tiene dispositivos conectados permanentemente, la --deviceopción es la mejor opción. Si tiene dispositivos efímeros, esto es lo que he estado usando:
De forma predeterminada, los dispositivos en serie se montan para que solo los usuarios root puedan acceder al dispositivo. Necesitamos agregar una regla udev para que sean legibles por usuarios no root.
Cree un archivo llamado /etc/udev/rules.d/99-serial.rules. Agregue la siguiente línea a ese archivo:
KERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE = "0666" dará a todos los usuarios permisos de lectura / escritura (pero no ejecución) para sus dispositivos ttyUSB. Esta es la opción más permisiva, y es posible que desee restringir esto aún más según sus requisitos de seguridad. Puede leer en udev para obtener más información sobre cómo controlar lo que sucede cuando un dispositivo se conecta a una puerta de enlace Linux.
Los dispositivos en serie a menudo son efímeros (se pueden conectar y desconectar en cualquier momento). Debido a esto, no podemos montar en el dispositivo directo o incluso en la carpeta / dev / serial, porque pueden desaparecer cuando se desconectan las cosas. Incluso si los vuelve a enchufar y el dispositivo vuelve a aparecer, técnicamente es un archivo diferente al que estaba montado, por lo que Docker no lo verá. Por esta razón, montamos toda la carpeta / dev desde el host al contenedor. Puede hacer esto agregando el siguiente comando de volumen a su comando de ejecución Docker:
-v /dev:/dev
Si su dispositivo está conectado permanentemente, entonces usar la opción --device o un montaje de volumen más específico es probablemente una mejor opción desde una perspectiva de seguridad.
Si no usó la opción --device y se montó en toda la carpeta / dev, se le pedirá que ejecute el contenedor en modo privilegiado (voy a revisar las cosas de cgroup mencionadas anteriormente para ver si esto se puede eliminar ) Puede hacer esto agregando lo siguiente a su comando de ejecución Docker:
--privileged
Si su dispositivo se puede conectar y desconectar, Linux no garantiza que siempre se montará en la misma ubicación ttyUSBxxx (especialmente si tiene varios dispositivos). Afortunadamente, Linux creará un enlace simbólico automáticamente al dispositivo en la carpeta / dev / serial / by-id. El archivo en esta carpeta siempre se llamará igual.
Este es el resumen rápido, tengo un artículo de blog que entra en más detalles.
Es difícil para nosotros vincular un dispositivo USB específico a un contenedor acoplable que también es específico. Como puede ver, la forma recomendada de lograr es:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Unirá todos los dispositivos a este contenedor. No es seguro Todos los contenedores fueron otorgados para operarlos todos.
Otra forma es vincular dispositivos por devpath. Puede verse así:
docker run -t -i --privileged -v /dev/bus/usb/001/002:/dev/bus/usb/001/002 ubuntu bash
o --device(mejor, no privileged):
docker run -t -i --device /dev/bus/usb/001/002 ubuntu bash
Mucho más seguro. Pero en realidad es difícil saber cuál es el devpath de un dispositivo específico.
He escrito este repositorio para resolver este problema.
https://github.com/williamfzc/usb2container
Después de implementar este servidor, puede obtener fácilmente toda la información de los dispositivos conectados a través de la solicitud HTTP:
curl 127.0.0.1:9410/api/device
y obten:
{
"/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"
},
...
}
y atarlos a sus contenedores. Por ejemplo, puede ver que el DEVNAME de este dispositivo es /dev/bus/usb/001/120:
docker run -t -i --device /dev/bus/usb/001/120 ubuntu bash
Tal vez te ayude.
Con las últimas versiones de Docker, esto es suficiente:
docker run -ti --privileged ubuntu bash
Le dará acceso a todos los recursos del sistema (en / dev por ejemplo)
Además de las respuestas anteriores, para aquellos que desean una forma rápida de usar un dispositivo USB externo (HDD, unidad flash) que funcione dentro de la ventana acoplable y no utilicen el modo privilegiado:
Encuentre el devpath a su dispositivo en el host:
sudo fdisk -l
Puede reconocer su unidad por su capacidad de la lista con bastante facilidad. Copie esta ruta (para el siguiente ejemplo es /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
Monta este devpath (preferible a /media):
sudo mount <drive path> /media/<mount folder name>
Luego puede usar esto como un parámetro para docker rungustar:
docker run -it -v /media/<mount folder name>:/media/<mount folder name>
o en docker componer en volúmenes:
services:
whatevermyserviceis:
volumes:
- /media/<mount folder name>:/media/<mount folder name>
Y ahora, cuando corres e ingresas a tu contenedor, deberías poder acceder a la unidad dentro del contenedor en /media/<mount folder name>
DESCARGO DE RESPONSABILIDAD:
Si desea acceder dinámicamente a dispositivos USB que se pueden enchufar mientras el contenedor acoplable ya se está ejecutando, por ejemplo, acceda a una cámara web USB recién conectada en / dev / video0, puede agregar una regla cgroup al iniciar el contenedor. Esta opción no necesita un contenedor privilegiado y solo permite el acceso a tipos específicos de hardware.
Marque el número principal del dispositivo del tipo de dispositivo que desea agregar. Puede buscarlo en la documentación del kernel de Linux . O puede verificarlo para su dispositivo. Por ejemplo, para verificar el número principal del dispositivo para una cámara web conectada a / dev / video0, puede hacer una ls -la /dev/video0. Esto resulta en algo como:
crw-rw----+ 1 root video 81, 0 Jul 6 10:22 /dev/video0
Donde el primer número (81) es el número principal del dispositivo. Algunos números principales de dispositivos comunes:
Agregue reglas cuando inicie el contenedor acoplable:
--device-cgroup-rule='c major_number:* rmw'regla para cada tipo de dispositivo al que desee acceder-v /run/udev:/run/udev:ro-v /dev:/devEntonces, para agregar todas las cámaras web usb y dispositivos serial2usb a su contenedor docker, haga lo siguiente:
docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash