上次我检查时,Docker没有任何方法让容器访问主机串行或USB端口。有什么技巧可以做到吗?


当前回答

有几个选择。你可以使用——device标志,用户可以在没有——特权模式的情况下访问USB设备:

docker run -t -i --device=/dev/ttyUSB0 ubuntu bash

或者,假设您的USB设备在主机/dev/bus/usb上可用,并且驱动程序正在工作等,您可以使用特权模式和volumes选项将其挂载到容器中。例如:

docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash

注意,顾名思义,——privileged是不安全的,应该小心处理。

其他回答

在没有-特权模式的情况下安全正确地访问tty设备

只要一行一行地按照说明做,所有步骤都有说明

想法是正确配置cgroup规则。首先,让我们找到你的USB设备的cgroup属性。执行如下命令:

$ ls -l /dev/ | grep ttyUSB
crw-rw-rw-  1 root  dialout 188,   0 Mar  1 18:23 ttyUSB0 #Example output

根据输出,您可以看到tty设备的主要组在我的示例中是188,因此我将继续进行此操作。

你可以运行docker镜像,允许访问特定主号的设备范围,docker将在你的主机上为你添加所需的规则(这将以分离模式运行docker,我们稍后将附加到它):

docker run --device-cgroup-rule='c 188:* rmw' -itd --name my_container ubuntu

现在的想法是添加一个脚本,它将在每次USB设备插入或拔出时运行。这里和这里对传递参数的自定义规则做了一些解释。在ubuntu上,你应该以超级用户(sudo)的身份创建文件/etc/udev/rules.d/99-docker- ty.rules:

ACTION=="add", SUBSYSTEM=="tty", RUN+="/usr/local/bin/docker_tty.sh 'added' '%E{DEVNAME}' '%M' '%m'"
ACTION=="remove", SUBSYSTEM=="tty", RUN+="/usr/local/bin/docker_tty.sh 'removed' '%E{DEVNAME}' '%M' '%m'"

该文件将新的条目添加到您的规则中,基本上是说:每次tty设备被插入-添加或插入-删除时,运行提供的脚本并传递一些参数。如果你想要更具体,你可以使用udevadm info——name=<设备名>来查找其他可以过滤设备的参数。您可以测试这里建议的规则。要应用这些规则:

root@~$ udevadm control --reload 

现在我们需要以超级用户(sudo)的身份在/usr/local/bin/ docker_ty .sh中创建以下脚本。您可以看到它被设置为在我们之前创建的udev规则中运行。

#!/usr/bin/env bash  
                                                           
echo "Usb event: $1 $2 $3 $4" >> /tmp/docker_tty.log        
if [ ! -z "$(docker ps -qf name=env_dev)" ]                                     
then                                                                            
if [ "$1" == "added" ]                                                          
    then                                                                        
        docker exec -u 0 env_dev mknod $2 c $3 $4                               
        docker exec -u 0 env_dev chmod -R 777 $2                                
        echo "Adding $2 to docker" >> /tmp/docker_tty.log                
    else                                                                        
        docker exec -u 0 env_dev rm $2                                          
        echo "Removing $2 from docker" >> /tmp/docker_tty.log            
    fi                                                                          
fi 

这个脚本将在运行的docker容器中创建tty设备,或者根据设备是否插入或拔出来删除它(类似于Ubuntu机器的情况-每次设备插入时,您都可以在/dev/目录下看到它)。提示:检查/tmp/ docker_ty .log文件,以获得主机上的一些调试输出,以及这里建议的调试bash脚本。

别忘了让脚本可执行:

root@~$ chmod +x /usr/local/bin/docker_tty.sh

现在连接到docker,看看当你插入和拔出它时,设备是否出现在/dev/目录中:

docker exec -it my_container bash

有几个选择。你可以使用——device标志,用户可以在没有——特权模式的情况下访问USB设备:

docker run -t -i --device=/dev/ttyUSB0 ubuntu bash

或者,假设您的USB设备在主机/dev/bus/usb上可用,并且驱动程序正在工作等,您可以使用特权模式和volumes选项将其挂载到容器中。例如:

docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash

注意,顾名思义,——privileged是不安全的,应该小心处理。

还有一种更简单的共享usb设备的方法,没有——privileged标志。这样做:

Docker运行…——device=/dev/bus/usb——device=/dev/usb <container> .使用实例

--device works until your USB device gets unplugged/replugged and then it stops working. You have to use cgroup devices.allow get around it. You could just use -v /dev:/dev but that's unsafe as it maps all the devices from your host into the container, including raw disk devices and so forth. Basically this allows the container to gain root on the host, which is usually not what you want. Using the cgroups approach is better in that respect and works on devices that get added after the container as started.

在Docker中访问USB设备而不使用——特权

这有点难粘贴,但简而言之,你需要获得你的角色设备的主编号,并将其发送到cgroup:

188是/dev/ttyUSB*的主编号,可以通过'ls -l'获得。你的系统和我的系统可能不同:

root@server:~# echo 'c 188:* 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

如果不这样做,容器启动后任何新插入或重新启动的设备将获得一个新的总线ID,并且将不允许访问容器。

在当前版本的Docker中,你可以使用——device标志来实现你想要的,而不需要访问所有的USB设备。

例如,如果你想在Docker容器中只使/dev/ttyUSB0可访问,你可以这样做:

docker run -t -i --device=/dev/ttyUSB0 ubuntu bash