Востаннє я перевіряв, у Docker не було жодних засобів, щоб надати контейнерові доступ до послідовного хосту або USB-порту . Чи є хитрість, яка дозволяє це робити?
Востаннє я перевіряв, у Docker не було жодних засобів, щоб надати контейнерові доступ до послідовного хосту або USB-порту . Чи є хитрість, яка дозволяє це робити?
Відповіді:
Є пара варіантів. Ви можете використовувати --device
прапор, який може використовувати для доступу до USB-пристроїв без --privileged
режиму:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
Крім того, якщо припустити, що ваш USB-пристрій доступний з драйверами, що працюють тощо, на хості /dev/bus/usb
, ви можете встановити це в контейнер, використовуючи привілейований режим та опцію гучності . Наприклад:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Зауважте, що як випливає з назви, --privileged
це небезпечно і з ними слід ставитися обережно.
У поточних версіях Docker ви можете використовувати --device
прапор, щоб досягти бажаного, не потребуючи доступу до всіх USB-пристроїв.
Наприклад, якщо ви хочете зробити /dev/ttyUSB0
доступними лише у вашому контейнері Docker, ви можете зробити щось на кшталт:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
--device
прапор, як визначити, з яким /dev/<device>
пов’язаним пристроєм Android на хост-машині, особливо коли використовується термінал Docker Quickstart (VirtualBox Host) для Windows або Mac?
--device
працює, поки ваш USB-пристрій не вимкнеться / відключено від мережі, а потім він перестане працювати. Ви повинні використовувати пристрої групи. Дозвольте їх обійти.
Ви можете просто використовувати, -v /dev:/dev
але це небезпечно, оскільки він відображає всі пристрої з вашого хоста в контейнер, включаючи пристрої з необробленим диском тощо. В основному це дозволяє контейнеру отримати корінь на хості, що зазвичай не є тим, що потрібно.
Використання підходу cgroups в цьому відношенні краще і працює на пристроях, які додаються після запуску контейнера.
Деталі див. Тут: Доступ до USB-пристроїв у Docker без використання --privileged
Це трохи важко вставити, але в двох словах, вам потрібно отримати основне число вашого персонального пристрою і надіслати це в групу:
189 - основна кількість / dev / ttyUSB *, яку ви можете отримати з 'ls -l'. У вашій системі це може відрізнятися, ніж у моїй:
root@server:~# echo 'c 189:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allow
(A contains the docker containerID)
Потім запустіть контейнер так:
docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash debian:amd64
не роблячи цього, будь-який щойно підключений або перезавантажений пристрій після запуску контейнера отримає новий ідентифікатор шини і не буде дозволений доступ до контейнера.
189
потрібно замінити. Опис того, що надіслати, devices.allow
можна знайти тут: kernel.org/doc/Documentation/cgroup-v1/devices.txt
Я хотів би розширити відповіді, що вже були надані, щоб включити підтримку динамічно підключених пристроїв, які не захоплені, /dev/bus/usb
і як зробити це робочим при використанні хоста Windows разом із boot2docker VM.
Якщо ви працюєте з Windows, вам потрібно буде додати будь-які правила USB для пристроїв, до яких ви хочете, щоб Docker отримав доступ у менеджері VirtualBox. Для цього ви можете зупинити VM, запустивши:
host:~$ docker-machine stop default
Відкрийте диспетчер VirtualBox і додайте підтримку USB із необхідними фільтрами.
Запустіть boot2docker VM:
host:~$ docker-machine start default
Оскільки USB-пристрої підключені до VM boot2docker, команди потрібно запустити з цієї машини. Відкрийте термінал з VM та запустіть команду run docker:
host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash
Зауважте, що коли команда виконується так, то захоплюються лише раніше підключені USB-пристрої. Прапор томів потрібен лише у тому випадку, якщо ви хочете, щоб це працювало з пристроями, підключеними після запуску контейнера. У цьому випадку ви можете використовувати:
docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash
Зауважте, мені довелося використовувати, /dev
а не /dev/bus/usb
в деяких випадках, щоб захопити такий пристрій /dev/sg2
. Я можу лише припустити, що те саме було б справедливо і для таких пристроїв, як /dev/ttyACM0
або /dev/ttyUSB0
.
Команди запуску докера також будуть працювати з хостом Linux.
Інший варіант - налаштувати udev, який контролює, як встановлюються пристрої та які привілеї. Корисно для дозволу некорінного доступу до послідовних пристроїв. Якщо у вас постійно приєднані пристрої, --device
варіант є найкращим способом. Якщо у вас є ефемерні пристрої, ось що я використовував:
За замовчуванням послідовні пристрої змонтовані так, що до нього можуть отримати доступ лише користувачі root. Нам потрібно додати правило udev, щоб зробити їх читабельними не-root користувачами.
Створіть файл з іменем /etc/udev/rules.d/99-serial.rules. Додайте до цього файлу наступний рядок:
KERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE = "0666" надасть усім користувачам читання / запис (але не виконання) дозволів на ваші пристрої ttyUSB. Це найбільш дозволений варіант, і ви, можливо, захочете додатково обмежити це залежно від ваших вимог безпеки. Ви можете прочитати на udev, щоб дізнатися більше про контроль того, що відбувається, коли пристрій підключено до шлюзу Linux.
Серійні пристрої часто є ефемерними (їх можна підключити та від'єднати в будь-який час). Через це ми не можемо встановити прямий пристрій або навіть папку / dev / serial, оскільки вони можуть зникнути, коли речі від'єднані від мережі. Навіть якщо ви підключите їх знову, і пристрій з’явиться знову, файл технічно відрізняється від того, що встановлено, тому Docker його не побачить. З цієї причини ми монтуємо всю папку / dev від хоста до контейнера. Ви можете зробити це, додавши до команди Docker наступну команду том:
-v /dev:/dev
Якщо ваш пристрій постійно підключений, то кращим варіантом з точки зору безпеки є використання опції --device або більш конкретного кріплення гучності.
Якщо ви не використовували параметр --device і монтувались у всій папці / dev, вам буде потрібно запустити контейнер у привілейованому режимі (я збираюся перевірити згадані вище матеріали про групу, щоб побачити, чи можна це видалити ). Це можна зробити, додавши в команду запуску Docker наступне:
--privileged
Якщо ваш пристрій можна підключити та відключити від мережі, Linux не гарантує, що він завжди буде встановлений у тому ж самому місці ttyUSBxxx (особливо якщо у вас є кілька пристроїв). На щастя, Linux автоматично зробить символьне посилання на пристрій у папці / dev / serial / by-id. Файл у цій папці завжди буде називатися однаковим.
Це швидкий пробіг, у мене є стаття в блозі, яка детальніше описується.
Нам важко прив’язати конкретний USB-пристрій до докерного контейнера, який також є специфічним. Як бачите, рекомендований спосіб досягти:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Він прив’яже всі пристрої до цього контейнера. Це небезпечно. Кожен контейнер був наданий для експлуатації всіх.
Інший спосіб - прив'язка пристроїв devpath. Це може виглядати так:
docker run -t -i --privileged -v /dev/bus/usb/001/002:/dev/bus/usb/001/002 ubuntu bash
або --device
(краще, ні privileged
):
docker run -t -i --device /dev/bus/usb/001/002 ubuntu bash
Набагато безпечніше. Але насправді важко знати, що таке конкретний пристрій.
Я написав це репо, щоб вирішити цю проблему.
https://github.com/williamfzc/usb2container
Після розгортання цього сервера ви можете легко отримати всю інформацію про підключені пристрої через HTTP-запит:
curl 127.0.0.1:9410/api/device
і отримуй:
{
"/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"
},
...
}
і прив’яжіть їх до своїх контейнерів. Наприклад, ви можете бачити DEVNAME цього пристрою /dev/bus/usb/001/120
:
docker run -t -i --device /dev/bus/usb/001/120 ubuntu bash
Можливо, це допоможе.
Для останніх версій докера цього достатньо:
docker run -ti --privileged ubuntu bash
Це дасть доступ до всіх системних ресурсів (наприклад, in / dev)
Додаючи відповіді вище, для тих, хто хоче швидким способом використовувати зовнішній USB-пристрій (жорсткий диск, флешку), що працює всередині докера та не використовує приватний режим:
Знайдіть розробку до свого пристрою на хості:
sudo fdisk -l
Ви можете розпізнати свій привід за його місткістю досить легко зі списку. Скопіюйте цей шлях (для наступного прикладу це /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
Гора цей шлях (бажано /media
):
sudo mount <drive path> /media/<mount folder name>
Потім ви можете використовувати це як параметр, щоб docker run
подобатися:
docker run -it -v /media/<mount folder name>:/media/<mount folder name>
або в docker складати під томами:
services:
whatevermyserviceis:
volumes:
- /media/<mount folder name>:/media/<mount folder name>
А тепер, коли ви запустите та введете контейнер, ви повинні мати доступ до диска всередині контейнера /media/<mount folder name>
ВІДМОВА:
Якщо ви хочете динамічно отримувати доступ до USB-пристроїв, які можна підключити під час роботи контейнера докера, наприклад, отримати доступ до щойно приєднаної веб-камери usb за адресою / dev / video0, ви можете додати правило групи під час запуску контейнера. Цей параметр не потребує - привілейований контейнер і дозволяє лише доступ до певних типів обладнання.
Перевірте основну кількість пристрою типу пристрою, який ви хочете додати. Ви можете знайти його в документації на ядро Linux . Або ви можете перевірити це на своєму пристрої. Наприклад, для перевірки основного номера пристрою для веб-камери, підключеної до / dev / video0, ви можете зробити це ls -la /dev/video0
. Це призводить до такого типу:
crw-rw----+ 1 root video 81, 0 Jul 6 10:22 /dev/video0
Де перший номер (81) - основне число пристрою. Деякі основні номери основних пристроїв:
Додайте правила під час запуску контейнера докер:
--device-cgroup-rule='c major_number:* rmw'
правило для кожного типу пристроїв, до яких ви хочете отримати доступ-v /run/udev:/run/udev:ro
-v /dev:/dev
Отже, щоб додати всі веб-камери usb та serial2usb до вашого контейнера docker, зробіть:
docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash