В прошлый раз, когда я проверял, у Docker не было никаких средств, чтобы предоставить контейнеру доступ к последовательному порту хоста или порту USB. Есть ли хитрость, которая позволяет это сделать?
Docker - способ дать доступ к хосту USB или последовательному устройству?
Ответ 1
Есть несколько вариантов. Вы можете использовать флаг --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
небезопасен , и с ним следует обращаться осторожно.
Ответ 2
В текущих версиях Docker вы можете использовать флаг --device
для достижения того, чего вы хотите, без необходимости предоставлять доступ ко всем USB-устройствам.
Например, если вы хотите сделать доступным только /dev/ttyUSB0
в вашем контейнере Docker, вы можете сделать что-то вроде:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
Ответ 3
Я хотел бы расширить уже предоставленные ответы, чтобы включить поддержку динамически подключенных устройств, которые не перехватываются с /dev/bus/usb
и как заставить это работать при использовании хоста Windows вместе с виртуальной машиной boot2docker.
Если вы работаете с Windows, вам нужно добавить все правила USB для устройств, к которым вы хотите, чтобы Docker имел доступ в диспетчере VirtualBox. Для этого вы можете остановить виртуальную машину, запустив:
host:~$ docker-machine stop default
Откройте VirtualBox Manager и добавьте поддержку USB с фильтрами по мере необходимости.
Запустите boot2docker VM:
host:~$ docker-machine start default
Поскольку устройства USB подключены к виртуальной машине boot2docker, команды необходимо запускать с этого компьютера. Откройте терминал с виртуальной машиной и выполните команду docker run:
host:~$ docker-machine ssh
[email protected]:~$ docker run -it --privileged ubuntu bash
Обратите внимание, что когда команда запускается следующим образом, захватываются только ранее подключенные USB-устройства. Флаг томов требуется только в том случае, если вы хотите, чтобы он работал с устройствами, подключенными после запуска контейнера. В этом случае вы можете использовать:
[email protected]:~$ docker run -it --privileged -v /dev:/dev ubuntu bash
Обратите внимание, что в некоторых случаях мне приходилось использовать /dev
вместо /dev/bus/usb
для захвата устройства вроде /dev/sg2
. Я могу только предположить, что то же самое будет верно для таких устройств, как /dev/ttyACM0
или /dev/ttyUSB0
.
Команды docker run также будут работать с хостом Linux.
Ответ 4
--device
работает до тех пор, пока ваше USB-устройство не будет отключено/повторно подключено, а затем перестанет работать. Вы должны использовать cgroup devices.allow обойти это.
Вы можете просто использовать -v /dev:/dev
, но это небезопасно, поскольку оно отображает все устройства вашего хоста в контейнер, включая устройства с необработанным диском и так далее. По сути, это позволяет контейнеру получить права root на хосте, что обычно не то, что вам нужно.
Использование подхода cgroups лучше в этом отношении и работает на устройствах, которые добавляются после контейнера при запуске.
Подробности здесь: Доступ к USB-устройствам в Docker без использования --privileged
Его немного сложно вставить, но в двух словах, вам нужно получить основной номер для вашего устройства персонажа и отправить его в cgroup:
189 - это главное число /dev/ttyUSB *, которое вы можете получить с помощью 'ls -l'. В вашей системе он может отличаться от моего:
[email protected]:~# 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
без этого любое новое подключенное или перезагружаемое устройство после запуска контейнера получит новый идентификатор шины и не получит доступ к контейнеру.
Ответ 5
Другой вариант - настроить udev, который управляет монтированием устройств и какими привилегиями. Полезно, чтобы разрешить доступ без полномочий root к последовательным устройствам. Если у вас есть постоянно подключенные устройства, --device
опцией --device
. Если у вас есть эфемерные устройства, вот что я использовал:
1. Установите правило Udev
По умолчанию последовательные устройства монтируются так, что только корневые пользователи могут получить доступ к устройству. Нам нужно добавить правило udev, чтобы сделать его читаемым пользователями без полномочий root.
Создайте файл с именем /etc/udev/rules.d/99-serial.rules. Добавьте следующую строку в этот файл:
KERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE = "0666" предоставит всем пользователям права на чтение/запись (но не выполнение) для ваших устройств ttyUSB. Это наиболее допустимый вариант, и вы можете ограничить его в зависимости от ваших требований безопасности. Вы можете прочитать об udev, чтобы узнать больше об управлении тем, что происходит, когда устройство подключено к шлюзу Linux.
2. Смонтировать в /dev папку с хоста на контейнер
Последовательные устройства часто бывают эфемерными (их можно подключать и отключать в любое время). Из-за этого мы не можем смонтировать в прямом устройстве или даже в папке /dev/serial, потому что они могут исчезнуть при отключении. Даже если вы подключите их снова и устройство снова появится, это технически файл, отличный от того, что был смонтирован, поэтому Docker его не увидит. По этой причине мы монтируем всю папку /dev с хоста в контейнер. Вы можете сделать это, добавив следующую команду громкости в команду запуска Docker:
-v/dev: /dev
Если ваше устройство постоянно подключено, то использование опции --device или более точного монтирования тома, вероятно, является лучшим вариантом с точки зрения безопасности.
3. Запустите контейнер в привилегированном режиме.
Если вы не использовали опцию --device и монтировали ее во всей папке /dev, вам потребуется запустить контейнер в привилегированном режиме (я собираюсь проверить материал cgroup, упомянутый выше, чтобы увидеть, можно ли это удалить). Вы можете сделать это, добавив следующее в команду запуска Docker:
--privileged
4. Доступ к устройству из папки /dev/serial/by-id
Если ваше устройство может быть подключено и отключено, Linux не гарантирует, что оно всегда будет установлено в одном и том же месте ttyUSBxxx (особенно если у вас несколько устройств). К счастью, Linux автоматически создаст символическую ссылку на устройство в папке /dev/serial/by-id. Файл в этой папке всегда будет называться одинаково.
Это краткое изложение, у меня есть статья в блоге, в которой более подробно.
Ответ 6
Для последних версий Docker этого достаточно:
docker run -ti --privileged ubuntu bash
Это даст доступ ко всем системным ресурсам (например, в /dev)
Ответ 7
Уважаемый Грег/Бхаргав Рао/Мачавити, мы потратили много часов на решение этой проблемы, и слишком много страниц (включая стекопоток) дали ответ, который был не очень полезен для USB-устройств, которые приходят и уходят, когда контейнер работает.
Поэтому я написал сообщение в блоге, чтобы объяснить все уровни этой проблемы и решение для каждого слоя. Там нет рекламы, я ничем не выигрываю, кроме как помогать другим не тратить время на поиск правильного решения. Вы смотрели на страницу?
Теперь, когда вы удалили мое сообщение, кажется, что даже если я отредактирую его, это не имеет значения, так как оно все еще удалено, я, очевидно, не могу связаться с вами, чтобы помочь с тем, как я должен отредактировать его, чтобы восстановить его, и я по-видимому, осталось сделать это новое не по теме сообщение, которое вы, вероятно, тоже удалите.
Учитывая, что мое намерение состояло в том, чтобы действительно помочь другим с этой проблемой, можете ли вы предложить, что я должен делать? Я бы предпочел не вставлять всю веб-страницу в сообщение, если в этом есть смысл, много текста.
Я уже начал редактировать предыдущий пост, пока не понял, что это бессмысленно, так как он был удален.
Пожалуйста, порекомендуйте. Вы можете прокомментировать этот пост о том, как я должен изменить содержание дальше, если версия ниже не в порядке, и я могу удалить этот заголовок после этого.
--device работает до тех пор, пока ваше USB-устройство не будет отключено/повторно подключено, а затем перестанет работать. Вы должны использовать cgroup devices.allow обойти это.
Подробности здесь: http://marc.merlins.org/perso/linux/post_2018-12-20_Accessing-USB-Devices-In-Docker-ttyUSB0-dev-bus-usb--for-fastboot-adb_-without-using- privileged.html
Его немного сложно вставить, но в двух словах, вам нужно получить главный номер для вашего устройства персонажа и отправить его в cgroup:
root @server: ~ # echo 'c 189: * rwm'>/sys/fs/cgroup/devices/docker/$A*/devices.allow
(A содержит идентификатор контейнера Docker)
без этого любое новое подключенное или перезагружаемое устройство после запуска контейнера получит новый идентификатор шины и не получит доступ к контейнеру.