我正在尝试开发一个泊坞窗映像以测试可在MacOS和Windows上运行的SocketCAN(使用vcan),并且一切正常,直到我运行 candump vcan0 ,该操作返回:“ socket:Address family协议不支持”
一段时间后,我通过使用“ --network = host --privileged”启动容器,设法使它在Linux上运行。不过,这在Mac上启动的容器上不起作用,该容器返回:
socket: Address family not supported by protocol
一条“ candump vcan0”的痕迹表明它停止了此调用:
socket(AF_CAN, SOCK_RAW, 1) = -1 EAFNOSUPPORT (Address family not supported by protocol)
奇怪的是,即使在Mac(https://docs.docker.com/network/host/)上不支持“ --network = host”,该容器的主机名仍显示LinuxKit映像(运行这些容器的VM):< / p>
root@linuxkit-025000000001:~#
当然会加载vcan模块:
root@linuxkit-025000000001:~# lsmod
Module Size Used by
vcan 16384 0
xfrm_user 32768 1
xfrm_algo 16384 1 xfrm_user
我不知道还能尝试什么;)
答案 0 :(得分:2)
我最近经历了同样的痛苦,终于使它起作用。
这是我所做的:
1)克隆https://github.com/linuxkit/linuxkit.git
2)按照此处的说明根据需要修改内核:https://github.com/linuxkit/linuxkit/blob/master/docs/kernels.md#modifying-the-kernel-config
特别是要添加CAN网络作为模块和CAN vcan驱动程序作为模块。
3)将修改后的配置(例如config-4.9.x-x86_64
)复制到linuxkit/kernel
,以覆盖已经存在的配置。
4)从linuxkit/kernel
运行make build_4.9.x HASH=mods HASH_COMMIT=HEAD
5)使用下面的简单Dockerfile(称为“ Dockerfile.kernel”)运行docker build . -f Dockerfile.kernel -t kernel_extract
(执行此操作的方法可能更优雅,但我有点像docker n00b)。
6)使用docker run -it --entrypoint=/bin/sh kernel_extract
7)在图像中,通过执行以下操作提取模块:
cd /ksrc
tar -xvf kernel.tar
find lib/modules/ -name "*.ko" | grep can > /tmp/files
tar cpzf can.tar.gz -T /tmp/files
8)在容器仍在运行时,使用以下命令复制压缩包:
id=$(docker container ls | grep kernel_extract | awk '{print $1}')
docker cp $id:/ksrc/can.tar.gz .
9)在您的docker映像中安装can.tar.gz
文件。
10)使用--net=host
和--cap-add=ALL
运行docker映像,以确保可以加载内核模块并设置接口。
11)启动docker映像时,您需要运行类似这样的代码(在您的容器中,我在入口点上使用了shell脚本来执行此操作,然后执行我真正想做的事情):
for module in "can" "can-raw" "can-gw" "can-bcm" "can-dev" "vcan"; do
module_name=$(echo $module | tr "-" "_")
lsmod | grep $module_name >/dev/null
if [ $? -ne 0 ]; then
insmod $(find /lib/modules -name "${module}.ko")
fi
done
for iface in "can0" "can1"; do
ip link show $iface >/dev/null 2>&1
if [ $? -ne 0 ]; then
ip link add $iface type vcan
ip link set $iface up
fi
done
由于您弄乱了主机内核(在本例中为在Mac上运行的hyperkit vm),它将在每个单独的容器运行之后持续存在,这就是为什么要仔细检查它是否不尝试insmod的原因两次。
不幸的是,这有点令人费解,也许有人对docker细微差别的了解可以描述出一种更为优雅的方式,但这确实可行!
Dockerfile.kernel:
FROM linuxkit/kernel:4.9.184-mods-amd64 AS ksrc
FROM linuxkit/alpine:3fdc49366257e53276c6f363956a4353f95d9a81 AS build
RUN apk add build-base
COPY --from=ksrc / /ksrc
ENTRYPOINT ["/bin/sh"]