上次我检查时,Docker没有任何方法让容器访问主机串行或USB端口。有什么技巧可以做到吗?
当前回答
对于最新版本的docker,这就足够了:
docker run -ti --privileged ubuntu bash
它将允许访问所有系统资源(例如/dev)
其他回答
我们很难将特定的USB设备绑定到同样特定的docker容器上。如你所见,推荐的实现方式是:
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(最好没有特权):
docker run -t -i --device /dev/bus/usb/001/002 ubuntu bash
更安全。但实际上很难知道特定设备的devpath是什么。
我写了这个repo来解决这个问题。
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中,你可以使用——device标志来实现你想要的,而不需要访问所有的USB设备。
例如,如果你想在Docker容器中只使/dev/ttyUSB0可访问,你可以这样做:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
还有一种更简单的共享usb设备的方法,没有——privileged标志。这样做:
Docker运行…——device=/dev/bus/usb——device=/dev/usb <container> .使用实例
在没有-特权模式的情况下安全正确地访问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
对于最新版本的docker,这就足够了:
docker run -ti --privileged ubuntu bash
它将允许访问所有系统资源(例如/dev)
推荐文章
- 如何从DockerFile运行docker实例?
- 我是否试图连接到启用TLS的没有TLS的守护进程?
- Docker -一种访问主机USB或串行设备的方法?
- Docker:无效引用格式
- 将AWS凭证传递给Docker容器的最佳方法是什么?
- 如何在docker-compose中设置主机名?
- 为什么Docker容器映像这么大?
- 如何在docker撰写版本3中指定内存和CPU限制
- Docker和安全密码
- 如何让Docker容器在系统引导时自动启动?
- 如何在Docker容器中用模式初始化MySQL数据库?
- PYTHONUNBUFFERED在docker文件中的用途是什么?
- 如何在Dockerfile CMD中使用变量?
- 将主机端口转发到docker容器
- “docker compose”与“docker-compose”的区别