Na última vez que verifiquei, o Docker não tinha meios de fornecer acesso ao contêiner para hospedar a porta serial ou USB . Existe um truque que permita fazer isso?
Na última vez que verifiquei, o Docker não tinha meios de fornecer acesso ao contêiner para hospedar a porta serial ou USB . Existe um truque que permita fazer isso?
Respostas:
Há um par de opções. Você pode usar o --device
sinalizador usado para acessar dispositivos USB sem o --privileged
modo:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
Como alternativa, supondo que seu dispositivo USB esteja disponível com drivers funcionando, etc. no host /dev/bus/usb
, você pode montá-lo no contêiner usando o modo privilegiado e a opção de volumes . Por exemplo:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Observe que, como o nome indica, --privileged
é inseguro e deve ser manuseado com cuidado.
Com as versões atuais do Docker, você pode usar o --device
sinalizador para conseguir o que deseja, sem precisar conceder acesso a todos os dispositivos USB.
Por exemplo, se você deseja tornar /dev/ttyUSB0
acessível apenas dentro do contêiner do Docker, pode fazer algo como:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
--device
sinalizador, como determino qual /dev/<device>
é o dispositivo Android associado na máquina host, especialmente ao usar o Docker Quickstart Terminal (VirtualBox Host) para Windows ou Mac?
--device
funciona até o seu dispositivo USB ser desconectado / reconectado e depois parar de funcionar. Você tem que usar cgroup devices.allow contornar isso.
Você pode simplesmente usar, -v /dev:/dev
mas isso não é seguro, pois mapeia todos os dispositivos do seu host para o contêiner, incluindo dispositivos de disco bruto e assim por diante. Basicamente, isso permite que o contêiner ganhe raiz no host, o que geralmente não é o que você deseja.
O uso da abordagem cgroups é melhor nesse aspecto e funciona em dispositivos que são adicionados após o contêiner como iniciado.
Veja detalhes aqui: Acessando dispositivos USB no Docker sem usar --privileged
É um pouco difícil de colar, mas, em poucas palavras, você precisa obter o número principal do seu dispositivo de personagem e enviá-lo ao cgroup:
189 é o número principal de / dev / ttyUSB *, que você pode obter com 'ls -l'. Pode ser diferente no seu sistema e no meu:
root@server:~# echo 'c 189:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allow
(A contains the docker containerID)
Então inicie seu contêiner assim:
docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash debian:amd64
sem fazer isso, qualquer dispositivo recém-conectado ou reiniciado após o contêiner iniciar, receberá um novo ID de barramento e não terá acesso permitido ao contêiner.
189
deve ser substituído. Uma descrição do que para enviar devices.allow
podem ser encontrados aqui: kernel.org/doc/Documentation/cgroup-v1/devices.txt
Eu queria estender as respostas já fornecidas para incluir suporte para dispositivos conectados dinamicamente que não são capturados /dev/bus/usb
e como fazê-lo funcionar ao usar um host do Windows junto com a VM do boot2docker.
Se você estiver trabalhando com o Windows, precisará adicionar regras de USB para dispositivos que você deseja que o Docker acesse no gerenciador do VirtualBox. Para fazer isso, você pode parar a VM executando:
host:~$ docker-machine stop default
Abra o VirtualBox Manager e adicione suporte USB com filtros, conforme necessário.
Inicie a VM boot2docker:
host:~$ docker-machine start default
Como os dispositivos USB estão conectados à VM boot2docker, os comandos precisam ser executados a partir dessa máquina. Abra um terminal com a VM e execute o comando docker run:
host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash
Observe que, quando o comando é executado dessa maneira, somente os dispositivos USB conectados anteriormente serão capturados. O sinalizador de volumes é necessário apenas se você desejar que isso funcione com dispositivos conectados após o contêiner ser iniciado. Nesse caso, você pode usar:
docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash
Note, eu tive que usar em /dev
vez de /dev/bus/usb
em alguns casos para capturar um dispositivo como /dev/sg2
. Só posso supor que o mesmo seria verdadeiro para dispositivos como /dev/ttyACM0
ou /dev/ttyUSB0
.
Os comandos de execução do docker também funcionarão com um host Linux.
Outra opção é ajustar o udev, que controla como os dispositivos são montados e com quais privilégios. Útil para permitir acesso não raiz a dispositivos seriais. Se você tiver dispositivos permanentemente ligado, a --device
opção é a melhor maneira de ir. Se você tem dispositivos efêmeros, aqui está o que eu tenho usado:
Por padrão, os dispositivos seriais são montados para que apenas usuários raiz possam acessar o dispositivo. Precisamos adicionar uma regra do udev para torná-los legíveis por usuários não raiz.
Crie um arquivo chamado /etc/udev/rules.d/99-serial.rules. Adicione a seguinte linha a esse arquivo:
KERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE = "0666" dará a todos os usuários permissões de leitura / gravação (mas não execução) nos seus dispositivos ttyUSB. Essa é a opção mais permissiva e você pode restringir ainda mais isso, dependendo dos seus requisitos de segurança. Você pode ler no udev para saber mais sobre como controlar o que acontece quando um dispositivo é conectado a um gateway Linux.
Os dispositivos seriais geralmente são efêmeros (podem ser conectados e desconectados a qualquer momento). Por esse motivo, não podemos montar no dispositivo direto ou na pasta / dev / serial, porque eles podem desaparecer quando as coisas são desconectadas. Mesmo se você conectá-los novamente e o dispositivo aparecer novamente, é tecnicamente um arquivo diferente do que foi montado, para que o Docker não o veja. Por esse motivo, montamos toda a pasta / dev do host para o contêiner. Você pode fazer isso adicionando o seguinte comando de volume ao comando de execução do Docker:
-v /dev:/dev
Se o seu dispositivo estiver permanentemente conectado, usar a opção --device ou uma montagem de volume mais específica provavelmente será uma opção melhor do ponto de vista da segurança.
Se você não usou a opção --device e montou toda a pasta / dev, será necessário executar o contêiner no modo privilegiado (vou verificar o material do cgroup mencionado acima para ver se isso pode ser removido ) Você pode fazer isso adicionando o seguinte ao comando de execução do Docker:
--privileged
Se o seu dispositivo puder ser conectado e desconectado, o Linux não garante que ele seja sempre montado no mesmo local ttyUSBxxx (especialmente se você tiver vários dispositivos). Felizmente, o Linux fará um link simbólico automaticamente para o dispositivo na pasta / dev / serial / by-id. O arquivo nesta pasta sempre terá o mesmo nome.
Este é o resumo rápido, eu tenho um artigo de blog que entra em mais detalhes.
É difícil vincular um dispositivo USB específico a um contêiner de docker, que também é específico. Como você pode ver, a maneira recomendada de obter é:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Ele vinculará todos os dispositivos a esse contêiner. Não é seguro. Todos os contêineres foram concedidos para operar todos eles.
Outra maneira é ligar dispositivos pelo devpath. Pode parecer com:
docker run -t -i --privileged -v /dev/bus/usb/001/002:/dev/bus/usb/001/002 ubuntu bash
ou --device
(melhor, não privileged
):
docker run -t -i --device /dev/bus/usb/001/002 ubuntu bash
Muito mais seguro. Mas, na verdade, é difícil saber qual é o caminho de desenvolvimento de um dispositivo específico.
Eu escrevi este repositório para resolver este problema.
https://github.com/williamfzc/usb2container
Após a implantação deste servidor, você pode obter facilmente todas as informações dos dispositivos conectados via solicitação HTTP:
curl 127.0.0.1:9410/api/device
e pegue:
{
"/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 vinculá-los aos seus contêineres. Por exemplo, você pode ver que DEVNAME deste dispositivo é /dev/bus/usb/001/120
:
docker run -t -i --device /dev/bus/usb/001/120 ubuntu bash
Talvez isso ajude.
Com as versões mais recentes do docker, isso é suficiente:
docker run -ti --privileged ubuntu bash
Dará acesso a todos os recursos do sistema (em / dev, por exemplo)
Além das respostas acima, para aqueles que desejam uma maneira rápida de usar um dispositivo USB externo (HDD, unidade flash) trabalhando dentro da janela de encaixe e não usando o modo privilegiado:
Encontre o devpath para o seu dispositivo no host:
sudo fdisk -l
Você pode reconhecer sua unidade por sua capacidade facilmente na lista. Copie este caminho (para o seguinte exemplo /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
Monte este devpath (preferível /media
):
sudo mount <drive path> /media/<mount folder name>
Você pode usar isso como um parâmetro para docker run
gostar:
docker run -it -v /media/<mount folder name>:/media/<mount folder name>
ou na janela de encaixe compor sob volumes:
services:
whatevermyserviceis:
volumes:
- /media/<mount folder name>:/media/<mount folder name>
E agora, quando você executar e entrar no seu contêiner, poderá acessar a unidade dentro do contêiner em /media/<mount folder name>
AVISO LEGAL:
Se você deseja acessar dinamicamente dispositivos USB que podem ser conectados enquanto o contêiner do docker já está em execução, por exemplo, acessar uma webcam usb recém-conectada em / dev / video0, você pode adicionar uma regra cgroup ao iniciar o contêiner. Esta opção não precisa de um contêiner --privileged e permite apenas o acesso a tipos específicos de hardware.
Verifique o número principal do dispositivo que você deseja adicionar. Você pode procurar na documentação do kernel do linux . Ou você pode verificá-lo para o seu dispositivo. Por exemplo, para verificar o número principal do dispositivo de uma webcam conectada a / dev / video0, você pode fazer a ls -la /dev/video0
. Isso resulta em algo como:
crw-rw----+ 1 root video 81, 0 Jul 6 10:22 /dev/video0
Onde o primeiro número (81) é o número principal do dispositivo. Alguns números principais de dispositivos comuns:
Adicione regras ao iniciar o contêiner do docker:
--device-cgroup-rule='c major_number:* rmw'
regra para cada tipo de dispositivo ao qual você deseja acessar-v /run/udev:/run/udev:ro
-v /dev:/dev
Para adicionar todas as webcams USB e dispositivos serial2usb ao seu contêiner de docker, faça:
docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash