docker编译openwrt
1 整体步骤
- docker构建编译所需的系统镜像
- 下载源代码
- 首次编译
- 选择自己需要的软件再次编译
- 集成第三方软件包编译/编译单独ipk
1.1 为什么要使用Docker编译?
- 因为容器可以随时创建、删除,但是如果你直接在系统上构建,系统被破坏了就不好恢复了!因此推荐使用Docker
- 如果你对Docker一无所知,可以看看入门教程,推荐这个 【【编程不良人】Docker&Docker-Compose 实战!】 https://www.bilibili.com/video/BV1wQ4y1Y7SE/?p=3&share_source=copy_web&vd_source=801146758c4483987cb1bd1d6f31883a
2 docker编译官方openwrt
2.1 构建编译所需的系统镜像
为了不让编译环境污染宿主机,采用docker的方式编译,由docker为我们创建一个专门用于编译openwrt的系统,执行docker build的时候会自动下载编译工具所需要的依赖。你可以使用别人写好的Dockerfile文件: https://github.com/mwarning/docker-openwrt-build-env
|
|
查看Dockerfile,可以看到是基于debian的系统,安装了一些依赖,并创建了一个user用户(原因是不能使用root用户编译,也不能使用sudo执行编译)
|
|
为了加快构建速度,使用国内的源,在FROM debian:buster
后面添加一行
|
|
此时Dockerfile如下
|
|
构建镜像
|
|
执行此命令后,我们本地就多出了一个安装好编译依赖的debian镜像
|
|
创建编译系统的容器(镜像类似于系统的安装光盘,是固定的,容器类似于安装后的系统,可以开机关机、安装软件)
|
|
进入容器
|
|
修改当前目录所属用户给user(这个user用户是在Dockerfile中创建的)
|
|
2.2 首次编译
经过上面的步骤,我们进入了一个已经准备好编译环境的系统,此时可以开始跟着官方的步骤开始编译了
下载openwrt源代码:
|
|
进入代码目录
|
|
2.2.1 选择稳定版本分支
最好使用稳定版 git checkout 指定版本
,而不是默认使用HEAD
分支,如果你不使用稳定版,会带来某些问题,比如opkg安装程序会报错内核版本不匹配
|
|
切换到指定版本
|
|
2.2.2 更新feeds
|
|
2.2.3 配置选项
|
|
先认识一下界面
在这个例子里面,我们暂时使用x86平台,到后面我们再使用指定的路由器平台,所以这些默认不动即可!
openwrt编译默认不带luci的web界面,你需要手动勾选安装,找到,
LuCI-> Collections-> luci,双击使得前面的变成*
符号
设置web界面为中文, 双击空格使得前面的< >
变成<*>
符号
|
|
我们选择x86平台就是为了能在宿主机上运行,为了能docker中运行openwrt,找到target image勾选tar.gz
(默认是勾选上的,没有自己勾上)
接着保存配置菜单,移动到Save,回车选择OK然后光标移动到EXIT退出菜单。
2.2.4 下载编译所需的库
|
|
-j$(nproc)
, 其中 nproc会返回你系统的最大线程数量,例如-j8表示7线程编译(会保留一个线程防止系统卡死)V=s
: 打印详细信息
2.2.5 开始编译
编译前,请确保有良好的科学环境,终端输入curl -I www.google.com
,检查状态码是否为200,如果卡住了说明网络环境不适合编译。
|
|
第一次编译推荐使用多线程编译,一个小时以内可以完成。单线程编译可能要5小时。
|
|
如果编译出错了,那么就单线程编译一遍,前面多线程编译过的内容会跳过。通常出问题都是网络问题。
|
|
加上V=s
后可以看到详细的错误信息,例如可能出现的网络问题
编译成功后,到这里你可以看到在bin/target/x86/64
目录下看到编译的固件
怎么在docker运行我们编译好的固件?请查看-> index.zh-cn
2.3 选择插件编译进固件
经过第一次编译后,后面再次编译速度就会快很多,这时候我们就可以选择自己需要的插件编译进固件里面,例如 samba4
|
|
找到LuCI->Applications->luci-app-samba4, 双击空格使得前面的<>
变成<*>
,其中*
表示集成进固件里面, M
表示作为ipk包。
2.3.1 网络共享samba4
光标移动到save,保存.config,然后再次编译,发现速度会快很多。
2.3.2 docker
|
|
提醒:仅针对x86平台,如果编译
luci-app-dockerman
,则需要自己手动勾选依赖dockerd
,否则docker无法正常启动
在Utilities下找到,把前面的设置成<*>
|
|
2.3.3 usb打印服务器
|
|
找到内核Kernal Modules
-> USB Support
|
|
2.3.4 usb挂载
Base System
中选中 block-mount
2.3.5 usb存储支持
|
|
提醒:dnsmasq和dnsmasq-full不能同时勾选。例如选中passwall第三方插件时,可能会出现这种情况,请到Base System中取消调dnsmasq的勾选
2.3.6 二次编译
|
|
2.4 集成第三方插件
经过上面的的步骤,你已经学会了基本的编译,此时可以尝试添加第三方的软件包 https://github.com/kenzok8/openwrt-packages
2.4.1 添加软件源
执行
|
|
找到LuCI->Applications,勾选需要的软件,依赖会自动勾选
2.4.2 插件集成到固件里面
按下空格选中M
表示作为ipk包编译
|
|
再次按下空格,出现*
表示集成到固件里面
|
|
然后开始编译
|
|
2.4.3 插件不集成到固件里面,而是单独作为ipk包
- 参考:
https://3mile.github.io/archives/2019/0813123100/
按下空格选中
M
表示作为ipk包编译
|
|
开始编译
|
|
ipk生成路径,可以使用find命令查找
|
|
|
|
然后把这些ipk上传到路由器上执行即可
|
|
或者在web界面上传安装
2.4.4 第三方插件源可能出现的问题
2.4.4.1 ERROR: package/feeds/kenzo/alist failed to build
|
|
2.4.4.2 ERROR: package/feeds/small/v2ray-plugin failed to build.
- 参考 https://github.com/fw876/helloworld/issues/836 原因是勾选passwall2的时候,自动勾选了v2ray-plugin,要么取消调v2raya-plugin,要么升级go版本
2.5 调整ROOT大小
注意:对于官方openwrt的固件,修改root分区大小后,如果刷到路由器里面,需要重新刷GPT和uboot,否则可能不生效。
找到 Target Images
-> (102) Root filesystem partition size (in MiB)
, 把102改为自己想要的大小。
2.6 自定义配置文件
- 参考1: https://openwrt.org/docs/guide-developer/toolchain/use-buildsystem#custom_files
- 参考2: https://openwrt.org/docs/guide-developer/uci-defaults 我们可以在编译根目录下创建files目录,相当于路由器的根目录。然后往里面新建etc/uci-defaults文件夹,这里面可以写自己定义的uci命令
|
|
往files/etc/uci-defaults/
添加脚本,等同于往路由器的/etc/uci-defaults/中添加脚本。
|
|
在99-custom添加自定义ip地址、dns和网关命令
|
|
然后编译出来的固件,就会使用你的自定义配置.
该目录中的所有脚本都会由boot服务自动执行,且仅在全新安装后的首次启动时执行!
- 如果它们以代码 0 退出,则它们随后将被删除。
- 以非零退出代码退出的脚本不会被删除,并将在下次启动时重新执行,直到它们也成功退出。
2.7 注意事项
如果你选择了自定义路由器平台,官方openwrt编译出来的是.itb
格式的固件,需要用到tftp刷机方式,不兼容常见的第三方uboot刷入方式。可参考教程:
- 官网: https://openwrt.org/docs/guide-user/installation/generic.flashing.tftp
- 恩山: https://www.right.com.cn/forum/thread-8338290-1-1.html
2.8 差异配置
暂时不清楚有什么优点
- 参考: https://openwrt.org/docs/guide-developer/uci-defaults
- uci命令: https://openwrt.org/docs/techref/uci
3 docker编译lede
简介:lede是openwrt的一个分支,默认使用中文,集成了一些基本的插件。
编译方法:类似openwrt,其实就是仿造 https://github.com/mwarning/docker-openwrt-build-env 这个编写了一个linux环境,然后在这个环境里面执行编译
这次我们不下载他们Dockerfile,而是自己仿造一个
|
|
构建镜像
|
|
运行镜像
|
|
3.1 首次编译
|
|
第一次编译建议不要勾选任何插件,因为第一次编译包含了很多基础包的编译,过程比较持久,如果加上了插件造成报错可能会感到困惑:到底是插件的问题,还是我系统没配置好?因此第一次仅仅勾选你的路由器平台即可。这里拿RAX3000M举例,首先选择平台,接着是芯片,第三项是具体型号
3.2 自定义配置
默认情况下,openwrt和lede后台地址都是192.168.1.1,有没有办法在编译的时候自定义呢?当然可以,只需要在编译的根目录下创建文件夹files,然后往里面添加初始化脚本即可。files相当于路由器的根目录
|
|
假设我们要自定义ip地址
|
|
往里面添加内容
|
|
- 注意到我这里删掉了uhttpd的https监听地址,原因是lede默认没有安装luci-app-openssl,如果不关闭https监听会无法启动web界面(仅x86)
开始编译固件 (-j 后面是线程数)
|
|
如果发现编译出错,那么可以使用单线程编译,并输出详细信息。大部分情况下的首次编译出现错误都是网络问题。
|
|
编译完成后,可以在bin/target/平台目录下看到自己编译后的包,其中 xxx-squashfs-sysupgrade.bin
就是我们要的固件
3.3 集成插件编译
经过前面的首次编译后,一些基础的包都已经编译完成,再次编译时候会跳过他们。此时选择自己需要的插件编译速度,就取决于插件本身。
|
|
选择自己的插件后
|
|
注意,勾选luci应用后,依赖会自动勾选上,此时再次取消勾选luci,依赖不会取消,如果需要重新配置,请删掉.config
|
|
或者再选择插件前,先备份一下.config
|
|
3.4 拓展包
一些发行版会添加自己的拓展包,例如lede和immortalWRT的代码中都有automount和autosamba,但是这些官方openwrt是没有的。
3.4.1 ipv6支持
默认情况下lede的代码没有勾选ipv6-helper,请到 Extra pckages勾选ipv6-helper
3.4.2 自动挂载
Extra packages -> automount
3.4.3 自动网络共享
Extra packages -> autosamb
注意:这个脚本有BUG,在RAX3000M-emmc勾选了此拓展包会导致无线网络消失。删除后才能恢复,因此不建议使用此拓展包。详细信息: https://github.com/immortalwrt/immortalwrt/issues/1201
3.5 添加第三方插件源
与openwrt的相同,请参考上面
4 docker编译immortalwrt
- 地址: https://github.com/immortalwrt/immortalwrt
- 简介: immortalwrt甚至集成了很多第三方的软件包,无需额外添加软件源,感觉更方便,编译步骤和lede一样,过程不再赘述。
4.1 构建镜像
4.1.1 准备Dockerfile文件
Dockerfile文件,根据官网描述,建议基于ubuntu20.04-LTS,那么第一行的FROM就要改了
|
|
注意到这里还加了一行 DEBIAN_FRONTEND=noninteractive
,防止创建镜像的过程出现交互行为。
|
|
4.1.2 创建容器
|
|
4.1.3 进入容器
|
|
注意,docker里面的ubuntu系统需要修改用户目录权限给user才能下载源代码
|
|
4.2 首次编译
下载源代码
|
|
安装feeds
|
|
编译菜单,同样,先别选择插件,仅选择你的平台即可!
|
|
首次编译
|
|
选择插件后再次编译
|
|
5 编译的一些技巧
5.1 make选项
5.1.1 当多线程编译失败时,可以使用以下命令单线程编译,仅关注错误信息
|
|
另一种方法是检查相应的logs
文件夹,如make[3] -C package/kernel/mac80211 compile
,那么可以转到<buildroot>/logs/package/kernel/mac80211
查看compile.txt
5.1.2 报错时发出声音
|
|
5.1.3 忽视某个包的错误,继续编译其他包
加入某个包编译错误了,
|
|
5.2 tmux多窗口
tmux小技巧往期文章-> index.zh-cn
- 如果是远程ssh连接服务器编译,最好使用
tmux
,可以多窗口,且ssh断掉后进程不会中断,再次ssh进入服务器可以回到tmux会话。 创建一个名称为openwrt的session
|
|
面板垂直分割,键盘按下快捷键。以下<prefix>
表示同时按下Ctrl + B
。
- 例如下面这个命令,表示同时按下
Ctrl + B
后,松开键盘,再按下%
|
|
面板水平分割
|
|
退出tmux,但不退出tmux的进程
|
|
回到tmux
|
|
6 云编译:github action
没研究