我正在尝试使用这个 docker-compose 服务。
app:
build: ./
volumes:
- .:/app:delegated
devices:
- ${DEVICE:-/dev/null}:-/dev/ttyUSB*
运行时的响应
docker-compose up app
Error response from daemon: error gathering device information while adding custom device "/dev/ttyUSB*": no such file or directory
这里的想法是从本地获取所有与
/dev/ttyUSB*
匹配的设备并在容器内创建它们。这样我就可以在容器中拥有 0-N 个设备,处理没有设备连接时的场景。而且我不必知道每个设备的tty<id>
我读过一些旧答案,例如: 在 docker-compose 中映射所有可用设备 但这些要么使用
--privileged
或不回答如何复制和访问(所有 | 无设备)的问题。
我知道:
app:
build: ./
volumes:
- .:/app:delegated
devices:
- ${DEVICE:-/dev/null}:-/dev/ttyUSB0
可以工作,但当设备被分配不同的编号时则不起作用,因此需要将它们全部映射。
docker-compose
能够从 YAML
读取 STDIN
,因此只需即时生成即可。
假设我们的原始文件是:
abc:
container_name: abc
image: alpine
entrypoint: ["watch", "-n", "5", "ls"]
设备是:
$ ls -l /dev/ttyS*
crw-rw-rw- 1 root root 4, 64 Nov 11 09:34 /dev/ttyS0
crw-rw-rw- 1 root root 4, 65 Nov 11 09:34 /dev/ttyS1
crw-rw-rw- 1 root root 4, 66 Nov 11 09:34 /dev/ttyS2
crw-rw-rw- 1 root root 4, 67 Nov 11 09:34 /dev/ttyS3
所以,让我们将这些设备添加到
YAML
:
$ printf '%s\n%s' "$(cat docker-compose.yml)" "$(if [ "$(ls /dev/ttyS*)x" != "x" ]; then echo -e " devices:"; for D in /dev/ttyS*; do echo " - ${D}:${D//ttyS/ttyUSB}"; done; fi )"
将打印:
abc:
container_name: abc
image: alpine
entrypoint: ["watch", "-n", "5", "ls"]
devices:
- /dev/ttyS0:/dev/ttyUSB0
- /dev/ttyS1:/dev/ttyUSB1
- /dev/ttyS2:/dev/ttyUSB2
- /dev/ttyS3:/dev/ttyUSB3
现在让我们尝试使用
STDIN
运行 docker 容器:
$ printf '%s\n%s' "$(cat docker-compose.yml)" "$(if [ "$(ls /dev/ttyS*)x" != "x" ]; then echo -e " devices:"; for D in /dev/ttyS*; do echo " - ${D}:${D//ttyS/ttyUSB}"; done; fi )" | docker-compose -f /dev/stdin -f docker-compose.yml up -d
Creating abc ... done
让我们连接到容器并检查设备:
$ docker exec -it abc sh
# ls -l /dev
...
crw-rw-rw- 1 root root 4, 64 Nov 11 11:06 ttyUSB0
crw-rw-rw- 1 root root 4, 65 Nov 11 11:06 ttyUSB1
crw-rw-rw- 1 root root 4, 66 Nov 11 11:06 ttyUSB2
crw-rw-rw- 1 root root 4, 67 Nov 11 11:06 ttyUSB3
...
利润
另外,你可以查看这个答案
实际上,随着时间的推移,我找到了解决问题的另一种方法。 如果您想在不确切知道设备名称的情况下安装设备,您可以使用:
services:
service:
devices:
- /dev:/dev
这个简单的解决方案允许安装所有设备,但您需要事先更改其权限或添加
privileged
。另一个有趣的部分是,一旦您安装它,如果设备断开连接,然后您启动容器,然后连接设备,容器将不知道该设备,您需要重新启动它才能拾取它。