La dernière fois que j'ai vérifié, Docker n'avait aucun moyen de donner accès au conteneur au port série ou USB de l'hôte . Y a-t-il un truc qui permet de faire ça?
La dernière fois que j'ai vérifié, Docker n'avait aucun moyen de donner accès au conteneur au port série ou USB de l'hôte . Y a-t-il un truc qui permet de faire ça?
Réponses:
Il existe plusieurs options. Vous pouvez utiliser l' --device
indicateur que l'utilisation peut utiliser pour accéder aux périphériques USB sans --privileged
mode:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
Sinon, en supposant que votre périphérique USB est disponible avec des pilotes fonctionnant, etc. sur l'hôte dans /dev/bus/usb
, vous pouvez le monter dans le conteneur en utilisant le mode privilégié et l' option volumes . Par exemple:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Notez que comme son nom l'indique, --privileged
n'est pas sûr et doit être manipulé avec précaution.
Avec les versions actuelles de Docker, vous pouvez utiliser l' --device
indicateur pour réaliser ce que vous voulez, sans avoir besoin de donner accès à tous les périphériques USB.
Par exemple, si vous souhaitez rendre /dev/ttyUSB0
accessible uniquement dans votre conteneur Docker, vous pouvez faire quelque chose comme:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
--device
indicateur, comment déterminer quel /dev/<device>
est le périphérique Android associé sur la machine hôte, en particulier lors de l'utilisation du Docker Quickstart Terminal (VirtualBox Host) pour Windows ou Mac?
--device
fonctionne jusqu'à ce que votre périphérique USB soit débranché / rebranché, puis il cesse de fonctionner. Vous devez utiliser des périphériques de groupe de contrôle pour le contourner.
Vous pouvez simplement l'utiliser, -v /dev:/dev
mais ce n'est pas sûr car il mappe tous les périphériques de votre hôte dans le conteneur, y compris les périphériques de disque brut, etc. Fondamentalement, cela permet au conteneur de gagner la racine sur l'hôte, ce qui n'est généralement pas ce que vous voulez.
L'utilisation de l'approche cgroups est meilleure à cet égard et fonctionne sur les périphériques qui sont ajoutés après le démarrage du conteneur.
Voir les détails ici: Accéder aux périphériques USB dans Docker sans utiliser --privileged
C'est un peu difficile à coller, mais en un mot, vous devez obtenir le numéro majeur de votre périphérique de personnage et l'envoyer au groupe de contrôle:
189 est le nombre majeur de / dev / ttyUSB *, que vous pouvez obtenir avec «ls -l». Cela peut être différent sur votre système que sur le mien:
root@server:~# echo 'c 189:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allow
(A contains the docker containerID)
Ensuite, démarrez votre conteneur comme ceci:
docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash debian:amd64
sans cela, tout périphérique nouvellement branché ou redémarré après le démarrage du conteneur recevra un nouvel ID de bus et ne sera pas autorisé à accéder au conteneur.
189
doit être remplacé. Une description de ce qu'il faut envoyer devices.allow
peut être trouvée ici: kernel.org/doc/Documentation/cgroup-v1/devices.txt
Je voulais étendre les réponses déjà données pour inclure la prise en charge des appareils connectés dynamiquement qui ne sont pas capturés avec /dev/bus/usb
et comment faire fonctionner cela lors de l'utilisation d'un hôte Windows avec la VM boot2docker.
Si vous travaillez avec Windows, vous devrez ajouter des règles USB pour les périphériques auxquels vous souhaitez que Docker accède dans le gestionnaire VirtualBox. Pour ce faire, vous pouvez arrêter la VM en exécutant:
host:~$ docker-machine stop default
Ouvrez le gestionnaire VirtualBox et ajoutez la prise en charge USB avec des filtres si nécessaire.
Démarrez la VM boot2docker:
host:~$ docker-machine start default
Étant donné que les périphériques USB sont connectés à la machine virtuelle boot2docker, les commandes doivent être exécutées à partir de cette machine. Ouvrez un terminal avec la machine virtuelle et exécutez la commande docker run:
host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash
Notez que lorsque la commande est exécutée de cette manière, seuls les périphériques USB précédemment connectés seront capturés. L'indicateur de volumes n'est requis que si vous souhaitez que cela fonctionne avec les périphériques connectés après le démarrage du conteneur. Dans ce cas, vous pouvez utiliser:
docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash
Remarque, j'ai dû utiliser /dev
au lieu de /dev/bus/usb
dans certains cas pour capturer un appareil comme /dev/sg2
. Je ne peux que supposer qu'il en serait de même pour des appareils tels que /dev/ttyACM0
ou /dev/ttyUSB0
.
Les commandes d'exécution du docker fonctionneront également avec un hôte Linux.
Une autre option consiste à ajuster udev, qui contrôle la façon dont les périphériques sont montés et avec quels privilèges. Utile pour autoriser l'accès non root aux périphériques série. Si vous avez des périphériques connectés en permanence, l' --device
option est la meilleure solution. Si vous avez des appareils éphémères, voici ce que j'utilise:
Par défaut, les périphériques série sont montés de manière à ce que seuls les utilisateurs root puissent accéder au périphérique. Nous devons ajouter une règle udev pour les rendre lisibles par des utilisateurs non root.
Créez un fichier nommé /etc/udev/rules.d/99-serial.rules. Ajoutez la ligne suivante à ce fichier:
KERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE = "0666" donnera à tous les utilisateurs des autorisations de lecture / écriture (mais pas d'exécution) sur vos périphériques ttyUSB. Il s'agit de l'option la plus permissive et vous souhaiterez peut-être la restreindre davantage en fonction de vos exigences en matière de sécurité. Vous pouvez lire sur udev pour en savoir plus sur le contrôle de ce qui se passe lorsqu'un périphérique est connecté à une passerelle Linux.
Les appareils série sont souvent éphémères (peuvent être branchés et débranchés à tout moment). Pour cette raison, nous ne pouvons pas monter dans le périphérique direct ou même dans le dossier / dev / serial, car ceux-ci peuvent disparaître lorsque les choses sont débranchées. Même si vous les rebranchez et que l'appareil réapparaît, il s'agit techniquement d'un fichier différent de celui qui a été monté, donc Docker ne le verra pas. Pour cette raison, nous montons tout le dossier / dev de l'hôte vers le conteneur. Vous pouvez le faire en ajoutant la commande de volume suivante à votre commande d'exécution Docker:
-v /dev:/dev
Si votre appareil est connecté de manière permanente, utiliser l'option --device ou un montage de volume plus spécifique est probablement une meilleure option du point de vue de la sécurité.
Si vous n'avez pas utilisé l'option --device et monté dans tout le dossier / dev, vous devrez exécuter le conteneur en mode privilégié (je vais vérifier les éléments de groupe de contrôle mentionnés ci-dessus pour voir si cela peut être supprimé ). Vous pouvez le faire en ajoutant ce qui suit à votre commande d'exécution Docker:
--privileged
Si votre appareil peut être branché et débranché, Linux ne garantit pas qu'il sera toujours monté au même emplacement ttyUSBxxx (surtout si vous avez plusieurs appareils). Heureusement, Linux créera automatiquement un lien symbolique vers le périphérique dans le dossier / dev / serial / by-id. Le fichier de ce dossier sera toujours nommé de la même manière.
Voici le résumé rapide, j'ai un article de blog qui va dans plus de détails.
Il est difficile pour nous de lier un périphérique USB spécifique à un conteneur Docker qui est également spécifique. Comme vous pouvez le voir, la méthode recommandée pour y parvenir est:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Il liera tous les appareils à ce conteneur. C'est dangereux. Tous les conteneurs ont été autorisés à tous les exploiter.
Une autre méthode consiste à lier les périphériques par devpath. Cela peut ressembler à:
docker run -t -i --privileged -v /dev/bus/usb/001/002:/dev/bus/usb/001/002 ubuntu bash
ou --device
(mieux, non privileged
):
docker run -t -i --device /dev/bus/usb/001/002 ubuntu bash
Beaucoup plus sécuritaire. Mais en fait, il est difficile de savoir quel est le chemin de développement d'un périphérique spécifique.
J'ai écrit ce repo pour résoudre ce problème.
https://github.com/williamfzc/usb2container
Après avoir déployé ce serveur, vous pouvez facilement obtenir toutes les informations des appareils connectés via une requête HTTP:
curl 127.0.0.1:9410/api/device
et obtenir:
{
"/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"
},
...
}
et liez-les à vos conteneurs. Par exemple, vous pouvez voir que le DEVNAME de cet appareil est /dev/bus/usb/001/120
:
docker run -t -i --device /dev/bus/usb/001/120 ubuntu bash
Cela aidera peut-être.
Avec les dernières versions de docker, cela suffit:
docker run -ti --privileged ubuntu bash
Il donnera accès à toutes les ressources système (dans / dev par exemple)
Ajout aux réponses ci-dessus, pour ceux qui veulent un moyen rapide d'utiliser un périphérique USB externe (disque dur, lecteur flash) fonctionnant à l'intérieur du docker et n'utilisant pas le mode privilégié:
Recherchez le chemin de développement vers votre appareil sur l'hôte:
sudo fdisk -l
Vous pouvez reconnaître votre disque par sa capacité assez facilement dans la liste. Copiez ce chemin (pour l'exemple suivant /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
Montez ce devpath (préférable à /media
):
sudo mount <drive path> /media/<mount folder name>
Vous pouvez ensuite utiliser ceci comme paramètre pour docker run
aimer:
docker run -it -v /media/<mount folder name>:/media/<mount folder name>
ou en docker composez sous volumes:
services:
whatevermyserviceis:
volumes:
- /media/<mount folder name>:/media/<mount folder name>
Et maintenant, lorsque vous exécutez et entrez dans votre conteneur, vous devriez pouvoir accéder au lecteur à l'intérieur du conteneur à /media/<mount folder name>
AVERTISSEMENT:
Si vous souhaitez accéder dynamiquement aux périphériques USB qui peuvent être branchés alors que le conteneur Docker est déjà en cours d'exécution, par exemple accéder à une webcam USB juste connectée à / dev / video0, vous pouvez ajouter une règle de groupe de contrôle lors du démarrage du conteneur. Cette option ne nécessite pas de conteneur --privileged et autorise uniquement l'accès à des types de matériel spécifiques.
Vérifiez le numéro principal de l'appareil du type d'appareil que vous souhaitez ajouter. Vous pouvez le rechercher dans la documentation du noyau Linux . Ou vous pouvez le vérifier pour votre appareil. Par exemple, pour vérifier le numéro majeur du périphérique pour une webcam connectée à / dev / video0, vous pouvez faire un ls -la /dev/video0
. Cela donne quelque chose comme:
crw-rw----+ 1 root video 81, 0 Jul 6 10:22 /dev/video0
Où le premier nombre (81) est le numéro majeur de l'appareil. Quelques numéros majeurs de périphériques courants:
Ajoutez des règles lorsque vous démarrez le conteneur Docker:
--device-cgroup-rule='c major_number:* rmw'
règle pour chaque type d'appareil auquel vous souhaitez accéder-v /run/udev:/run/udev:ro
-v /dev:/dev
Donc, pour ajouter toutes les webcams USB et les périphériques serial2usb à votre conteneur docker, procédez comme suit:
docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash