上次我检查时,Docker没有任何方法让容器访问主机串行或USB端口。有什么技巧可以做到吗?
当前回答
对于最新版本的docker,这就足够了:
docker run -ti --privileged ubuntu bash
它将允许访问所有系统资源(例如/dev)
其他回答
除了上面的答案,对于那些想要快速使用外部USB设备(HDD,闪存驱动器)在docker内部工作,而不使用特权模式的人:
在主机上找到你的设备的devpath:
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
挂载这个devpath(最好是/media):
sudo mount <drive path> /media/<mount folder name>
然后你可以使用它作为docker运行的参数:
docker run -it -v /media/<mount folder name>:/media/<mount folder name>
或者在docker中合成volumes:
services:
whatevermyserviceis:
volumes:
- /media/<mount folder name>:/media/<mount folder name>
现在,当您运行并进入容器时,您应该能够访问容器中的驱动器/media/<挂载文件夹名>
免责声明:
这可能不适用于串行设备,如网络摄像头等。 我只对USB存储驱动器进行了测试。 如果您需要定期重新连接和断开设备,这 方法将会很烦人,并且除非重置挂载路径并重新启动容器,否则将无法工作。 我使用docker 17.06 +在文档中规定
--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,并且将不允许访问容器。
在没有-特权模式的情况下安全正确地访问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
还有一种更简单的共享usb设备的方法,没有——privileged标志。这样做:
Docker运行…——device=/dev/bus/usb——device=/dev/usb <container> .使用实例
对于最新版本的docker,这就足够了:
docker run -ti --privileged ubuntu bash
它将允许访问所有系统资源(例如/dev)
推荐文章
- E: gnupg, gnupg2和gnupg1似乎没有安装,但是这个操作需要其中一个
- 如何从docker更改默认docker注册表。IO到我的私人注册表?
- Docker- compose无法连接到Docker Daemon
- 单个命令停止和删除docker容器
- 使用GPU从docker容器?
- 如何使用本地映像作为dockerfile的基本映像?
- 谁能解释一下docker.sock
- 多重from是什么意思
- 通过映像名称停止Docker容器- Ubuntu
- 如果dockerfile的名称不是dockerfile,我如何构建一个dockerfile ?
- 守护进程的错误响应:已被集装箱使用"
- 如何从DockerFile运行docker实例?
- 我是否试图连接到启用TLS的没有TLS的守护进程?
- Docker -一种访问主机USB或串行设备的方法?
- Docker:无效引用格式