使用 Docker 编译 OpenWrt

请注意,本文编写于 338 天前,最后修改于 46 天前,其中某些信息可能已经过时。

前言

最近入了 OpenWrt 编译的坑,在经历过各种不顺利的编译体验后,我决定使用 Docker 去构建一个专门用于 OpenWrt 编译的系统环境容器。这样的好处是编译的过程始终在容器内进行,可以保持编译环境的高度一致性,基本上杜绝了因编译环境不同导致的编译失败的情况,有助于提高效率和编译成功率,同时省去了对编译环境的重复配置。

镜像特点

  • 基于 Ubuntu
  • 预装 OpenWrt 编译依赖软件包(免配置编译环境)
  • 预装 Zsh 与 Oh My Zsh(提升终端输入效率)
  • 预装 Tmux 与 Oh My Tmux(终端复用、后台运行)
  • 可挂载 buildroot 到宿主机(删除容器后源码与编译产物不会丢失)
  • 可通过 SSH 登录编译环境
  • 可通过 SFTP 取回编译产物

项目地址

GitHub: https://github.com/P3TERX/openwrt-build-env

Docker Hub: https://hub.docker.com/r/p3terx/openwrt-build-env

喜欢的小伙伴请随手点个star~

安装 Docker

GNU/Linux

curl -fsSL get.docker.com | sudo sh
curl -fsSL get.docker.com | sudo sh -s --mirror Aliyun # 中国大陆地区使用此命令加速安装
  • root用户需要把用户加入docker用户组:
sudo usermod -aG docker $USER
  • 启动 Docker
sudo systemctl enable docker
sudo systemctl start docker

其它系统

其它系统安装方法参见官方文档

TIPS: 使用 Windows 10 与 VMware 的组合的小伙伴需要注意,安装 Docker 要开启 Hyper-V ,这会导致 VMware 无法使用。可以选择安装 Linux 虚拟机中安装 Docker ,或者使用 WSL 编译

配置编译环境容器

NOTICE: 以下代码框中的命令都是一个整体,使用时注意完整复制粘贴。

建立容器

TIPS: 中国大陆网络环境建议先配置镜像加速器

建立容器并后台运行:

docker run -itd \
    --name openwrt-build-env \
    -h P3TERX \
    -p 10022:22 \
    -v ~/openwrt:/home/user/openwrt \
    p3terx/openwrt-build-env:18.04

可选/自定义项:

  • --name openwrt-build-env - 容器名称。
  • -h P3TERX - 容器主机名。
  • -p 10022:22 - SSH 端口映射,10022为宿主机端口。端口不能被占用,如需暴露在公网需修改防火墙设置。
  • -v ~/openwrt:/home/user/openwrt - 目录映射,实现容器内外文件共享,左边宿主机路径,右边容器路径。
  • p3terx/openwrt-build-env:18.04 - 可选 Ubuntu 系统版本: 18.0420.04。若不指定系统版本则默认为latest标签,一般会指向 Ubuntu 最新 LTS 版本。

设置目录文件权限

宿主机使用普通账户容器的情况下,使宿主机和容器之间可随意修改挂载目录中的文件,避免权限问题。若宿主机为 root 账户不要修改任何文件内容,否则会污染权限。


点击查看

修改 UID 与 GID

在宿主机输入id命令查看 UID 与 GID

若两者都为1000或者都为0(root 用户)则跳过这个步骤。
$ id
uid=1001(p3terx) gid=1002(p3terx)
  • 修改 UID(自行替换)
docker exec openwrt-build-env \
sudo usermod -u 1001 user
  • 修改 GID(自行替换)
docker exec openwrt-build-env \
sudo groupmod -g 1002 user
  • 重启容器
docker restart openwrt-build-env

修改文件归属

  • 修改文件归属用户和用户组为user
docker exec openwrt-build-env \
sudo chown -hR user:user .

验证结果

  • 进入容器
docker exec -it openwrt-build-env zsh
  • 输入la命令列出文件。当所有归属都为user说明没有问题了。
$ la
total 144K
-rw-r--r--  1 user user  220 Apr  5  2018 .bash_logout
-rw-r--r--  1 user user 3.7K Apr  5  2018 .bashrc
drwxr-xr-x  1 user user 4.0K Nov 18 12:14 .oh-my-zsh
-rw-r--r--  1 user user  807 Apr  5  2018 .profile
drwx------  1 user user 4.0K Nov 18 12:14 .ssh
drwxr-xr-x  1 user user 4.0K Nov 18 12:14 .tmux
lrwxrwxrwx  1 user user   16 Nov 18 12:14 .tmux.conf -> .tmux/.tmux.conf
-rw-r--r--  1 user user  11K Nov 18 12:14 .tmux.conf.local
-rw-r--r--  1 user user  42K Nov 18 13:04 .zcompdump
-rw-r--r--  1 user user  42K Nov 18 13:04 .zcompdump-P3TERX-5.4.2
-rw-------  1 user user  107 Nov 18 13:05 .zsh_history
-rw-r--r--  1 user user 3.6K Nov 18 12:14 .zshrc
drwxr-xr-x 16 user user 4.0K Nov 17 20:10 openwrt

SSH 安全设置

默认用户名和密码均为user,若需要把 SSH 端口暴露在公网,强烈建议修改密码或者使用密钥登录。


点击查看

修改密码

在宿主机执行以下命令修改密码。

docker exec -it openwrt-build-env \
sudo passwd user

为了方便构建镜像,对sudo进行了免密设置,比如执行sudo -i无需密码可直接切换到 root 账户为所欲为。

如果 SSH 端口暴露在公网且为密码登录的方式,那么强烈建议取消sudo免密,否则宿主机有被入侵的风险。

docker exec openwrt-build-env \
sudo rm -f /etc/sudoers.d/user

密钥登录

容器中已经建立好了.ssh目录,若想和宿主机共用一个密钥,只需把密钥认证文件复制进去即可。

docker cp ~/.ssh/authorized_keys openwrt-build-env:/home/user/.ssh

设置认证文件归属

docker exec openwrt-build-env \
sudo chown user:user /home/user/.ssh/authorized_keys

禁用密码登录

docker exec openwrt-build-env \
sudo sed -i '/PasswordAuthentication /c\PasswordAuthentication no' /etc/ssh/sshd_config

最后重启容器

docker restart openwrt-build-env

编译环境容器的基本操作

进入编译环境容器

  • 从宿主机进入容器
docker exec -it openwrt-build-env zsh
  • 通过 SSH 连接容器
ssh user@IP -p 10022
TIPS: 自行替换IP字段。宿主机可通过localhost127.0.0.1连接容器。

退出编译环境容器

快捷键Ctrl+D或输入exit命令可以退出容器操作界面。

容器会持续在后台运行,如果你不想占用资源,输入以下命令让容器停止运行。

docker stop openwrt-build-env

如果需要再次使用,输入以下命令启动编译环境容器。

docker start openwrt-build-env

开始编译

编译的过程就像复读机,几乎就是复制粘贴的过程。详细的编译步骤可以去看《OpenWrt 编译步骤与命令详解》,这里不做赘述了。

如果你想后台编译,这涉及到 Tmux 的使用,可自行搜索学习相关知识,其流程大致为:

  • tmux
  • 开始编译
  • 关闭窗口
  • tmux a
  • 查看编译结果

若挂载目录到宿主机,不要忘记把源码放入挂载的目录中。比如下面这样:

git clone https://github.com/coolsnowwolf/lede openwrt

找到编译的固件

如果你没有瞎改容器启动命令,那么不管是宿主机还是容器,它们的路径都是一样的。以 x86_64 平台为例子,固件所在路径为:

~/openwrt/bin/targets/x86/64
科普:~符号代表用户主目录,俗称家目录。其路径与当前登陆的用户有关,在 Linux 中普通用户家目录的路径是/home/用户名,而 root 用户是/root。Windowd 10 中路径是C:\Users\用户名。在 macOS 中路径是/Users/用户名

本博客已开设 Telegram 频道,欢迎小伙伴们订阅关注。

添加新评论

已有 4 条评论

编译OpenWrt过程难免需要科学上网,你是怎么让容器内走代理的
这几天试了很多方法 无一成功让Docker for Desktop下的容器走系统代理。在linux中很简单,-net host让容器网络运行在宿主机环境,然后直接连接到代理即可,但-net host在win和mac是不能用的。因为对于他们来说,-net host是vm而不是宿主机,然后其它的改成env也试了,本地代理会拒绝连接

P3TERX P3TERX 回复 @FOUNDwayOut
0 0

apt 和 curl 走代理就行了。

为什么我root用户创建的容器,git仍然提示没有权限?

root 用户不要在宿主机去动共享文件夹的文件。