我最近经历了同样的痛苦,终于让它工作了。
这是我所做的:
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) 当容器仍在运行时,将 tarball 复制出来:
id=$(docker container ls | grep kernel_extract | awk '{print $1}')
docker cp $id:/ksrc/can.tar.gz .
9)can.tar.gz
在你的 docker 镜像中安装文件。
10) 运行您的 docker 镜像,--net=host
并--cap-add=ALL
确保您可以加载内核模块并设置界面。
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"]