前言
之前的文章(香橙派5plus上跑云手机方案一 redroid(带硬件加快))在Ubuntu的docker里运行安卓,这里说下怎么在安卓手机下运行docker,测试也可以跑Ubuntu。
想在手机上运行docker想的不是一天两天了,其实很久之前就有这个想法了,只是奈何安卓内核一直编译不通过。现在觉得过了那么久,技能应该有点提拔了,觉得我又行了,所以又来试试。
测试用的手机是从闲鱼淘的一个一加七Pro(12+256G),使用的系统是Lineageos19.1,后面放出我运行的刷机包和编译的boot文件,你直接刷进手机应该就能运行了。
检查内核配置
首先检查下当前的安卓内核确实哪些运行docker需要的内核配置
先下载https://raw.githubusercontent.com/moby/moby/master/contrib/check-config.sh推送到手机的/data/local/tmp下: adb push check-config.sh /data/local/tmp/check-config.sh
然后使用adb root切换到root(需要再开发者模式里开启允许root调试),接着运行sh /data/local/tmp/check-config.sh查察。缺少的其实挺多
编译内核
要想在手机上原生运行docker,修改内核参数重新编译内核这个是绕不过去的,所以先开始编译内核。lineage的内核编译比较简朴,假如下载系统源码来编译的话基本没什么坑,这里就不多说了。有兴趣的可以看之前的文章:
- 为一加七Pro(LineageOs17.1 4.14内核版本)编译KernelSu
- wsl2-ubuntu20编译Lineage17(Android10)
运行docker也需要root权限,所以会将kernelsu一起编译进去,这里也不赘述了。
修改内核参数
先说一下修改内核参数的流程:
cd kernel/oneplus/sm8150 进到对应的内核源码根目次
export ARCH=arm64 指定内核编译的平台,不指定默认是x86
export SUBARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make vendor/sm8150-perf_defconfig 通过这个文件天生.config
make menuconfig 启动内核编辑菜单
make savedefconfig 生存.config文件为defconfig,至于这个和手动修改有什么区别就没细究了,反正都推荐用这个
mv defconfig arch/arm64/configs/vendor/sm8150-perf_defconfig 覆盖原先的内核配置文件,建议先备份一下原先的文件
rm .config
make可能有一个错误提示/bin/sh: 1: aarch64-linux-gnu-gcc: not found,通过搜索看到这个问答[1]说应该是缺少包:sudo apt-get install gcc-aarch64-linux-gnu
配置
这里为了方便直接抄别人的内核配置放到.config文件里: https://yzddmr6.com/posts/android-run-docker/
- CONFIG_NAMESPACES=y
- CONFIG_NET_NS=y
- CONFIG_PID_NS=y
- CONFIG_IPC_NS=y
- CONFIG_UTS_NS=y
- CONFIG_CGROUPS=y
- CONFIG_CGROUP_CPUACCT=y
- CONFIG_CGROUP_DEVICE=y
- CONFIG_CGROUP_FREEZER=y
- CONFIG_CGROUP_SCHED=y
- CONFIG_CPUSETS=y
- CONFIG_MEMCG=y
- CONFIG_KEYS=y
- CONFIG_VETH=y
- CONFIG_BRIDGE=y
- CONFIG_BRIDGE_NETFILTER=y
- CONFIG_IP_NF_FILTER=y
- CONFIG_IP_NF_TARGET_MASQUERADE=y
- CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
- CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
- CONFIG_NETFILTER_XT_MATCH_IPVS=y
- CONFIG_NETFILTER_XT_MARK=y
- CONFIG_IP_NF_NAT=y
- CONFIG_NF_NAT=y
- CONFIG_POSIX_MQUEUE=y
- CONFIG_NF_NAT_IPV4=y
- CONFIG_NF_NAT_NEEDED=y
- CONFIG_CGROUP_BPF=y
- CONFIG_USER_NS=y
- CONFIG_SECCOMP=y
- CONFIG_SECCOMP_FILTER=y
- CONFIG_CGROUP_PIDS=y
- CONFIG_MEMCG_SWAP=y
- CONFIG_MEMCG_SWAP_ENABLED=y
- CONFIG_IOSCHED_CFQ=y
- CONFIG_CFQ_GROUP_IOSCHED=y
- CONFIG_BLK_CGROUP=y
- CONFIG_BLK_DEV_THROTTLING=y
- CONFIG_CGROUP_PERF=y
- CONFIG_CGROUP_HUGETLB=y
- CONFIG_NET_CLS_CGROUP=y
- CONFIG_CGROUP_NET_PRIO=y
- CONFIG_CFS_BANDWIDTH=y
- CONFIG_FAIR_GROUP_SCHED=y
- CONFIG_RT_GROUP_SCHED=y
- CONFIG_IP_NF_TARGET_REDIRECT=y
- CONFIG_IP_VS=y
- CONFIG_IP_VS_NFCT=y
- CONFIG_IP_VS_PROTO_TCP=y
- CONFIG_IP_VS_PROTO_UDP=y
- CONFIG_IP_VS_RR=y
- CONFIG_SECURITY_SELINUX=y
- CONFIG_SECURITY_APPARMOR=y
- CONFIG_EXT4_FS=y
- CONFIG_EXT4_FS_POSIX_ACL=y
- CONFIG_EXT4_FS_SECURITY=y
- CONFIG_VXLAN=y
- CONFIG_BRIDGE_VLAN_FILTERING=y
- CONFIG_CRYPTO=y
- CONFIG_CRYPTO_AEAD=y
- CONFIG_CRYPTO_GCM=y
- CONFIG_CRYPTO_SEQIV=y
- CONFIG_CRYPTO_GHASH=y
- CONFIG_XFRM=y
- CONFIG_XFRM_USER=y
- CONFIG_XFRM_ALGO=y
- CONFIG_INET_ESP=y
- CONFIG_INET_XFRM_MODE_TRANSPORT=y
- CONFIG_IPVLAN=y
- CONFIG_MACVLAN=y
- CONFIG_DUMMY=y
- CONFIG_NF_NAT_FTP=y
- CONFIG_NF_CONNTRACK_FTP=y
- CONFIG_NF_NAT_TFTP=y
- CONFIG_NF_CONNTRACK_TFTP=y
- CONFIG_AUFS_FS=y
- CONFIG_BTRFS_FS=y
- CONFIG_BTRFS_FS_POSIX_ACL=y
- CONFIG_BLK_DEV_DM=y
- CONFIG_DM_THIN_PROVISIONING=y
- CONFIG_OVERLAY_FS=y
复制代码 然后使用make menuconfig在界面上一个一个查察配置的开启情况,发现CONFIG_BRIDGE_VLAN_FILTERING没有开启,查察了下是由于依赖项VLAN_8021Q没有开启
而CONFIG_IPVLAN则是依赖项NET_L3_MASTER_DEV没开启
所以在配置文件里再加上这两个配置, 再运行make menuconfig生存
- CONFIG_VLAN_8021Q=y
- CONFIG_BRIDGE_VLAN_FILTERING=y
- CONFIG_NET_L3_MASTER_DEV=y
- CONFIG_IPVLAN=y
复制代码 CONFIG_CGROUP_HUGETLB依赖于HUGETLB_PAGE,但是将这个配置直接加到.config不生效,界面上也不显示具体的开启路径
问了下gpt说是在File systems -> Pseudo filesystems -> HugeTLB file system support,在界面上启用,再在配置文件里加上CONFIG_CGROUP_HUGETLB,再打开界面看到就是启用状态。
预备工作都做完了,然后按照上面的命令生存为defconfig在覆盖原先的内核配置就可以开始编译了
开始编译
这里需要到lineage源码根目次,而不是在内核源码根目次
source build/envsetup.sh breakfast guacamole make bootimage
接着就会出现一个折磨我两周的错误:
aarch64-linux-gnu-ld is not allowed to be used. See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information.
虽然他给了一个链接让我们从内里看更多信息,链接里也给了办理方法:
但是试了也是没用,
用谷歌搜索也搜不出什么有用的方法,这两天忽然想能不能修改它提到的build/soong/ui/build/paths/config.go文件,问了下gpt,它说在config.go里的Configuration里加一行"aarch64-linux-gnu-ld": Allowed,就可以
试了下确实是可以,偶然候gpt就很好用。我开始还以为是将ld改成Allowed,由于前面明显是前缀。然后等待几分钟就编译完成了
将天生的boot.img在fastboot模式下用fastboot flash boot boot.img输入手机后启动手机。
检测结果
编译完的内核还有三个地方是红色(missing)
第一处经测试不是内核参数的题目,需要运行一次这行命令:sudo mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup,下面两个无法办理,由于黑白必须项,先不管它了。
补丁
有的提到还需要对net/netfilter/xt_qtaguid.c做补丁,但我这个内核代码里没有这个文件就跳过了。
增补
为了避免内核参数有遗漏,我们把https://github.com/lateautumn233/android_kernel_docker里的提到的内核参数也加到.config里,再重新编译一次。
运行docker
目前看到的运行docker有两种方式:
这里我选择第一种,第一种更成熟一点,许多东西都已经帮我们做好了。
termux
- # The main termux repository, with cloudflare cache
- deb https://packages-cf.termux.dev/apt/termux-main/ stable main
- # The main termux repository, without cloudflare cache
- # deb https://packages.termux.dev/apt/termux-main/ stable main
复制代码 证书错误
使用apt安装包时出现下面的证书无效。
Certificate verification failed: The certificate is NOT trusted. The certificate chain uses not yet valid certificate.
发现是手机的系统时间不对,没有在证书的有用时间内,修改下系统时间就好了。这个我是安装了一个via浏览器去访问百度,也跳出了证书不安全的提示,然后点击证书进去就看到证书有用时间是2023-12到2024-12的范围,而手机的时间是2022,就猜测是时间不对。
换apt源
https://mirrors.tuna.tsinghua.edu.cn/help/termux/
将下面的内容老师存为a.sh,然后用adb push a.sh /data/local/tmp/a.sh
- sed -i 's@^\(deb.*stable main\)$@#\1\ndeb https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main stable main@' $PREFIX/etc/apt/sources.list
- apt update && apt upgrade
复制代码 接着在termux终端输入sh /data/local/tmp/a.sh就好了。
远程
apt install openssh
sshd 启动ssh服务
whoami 查察当前用户
passwd 设置暗码
当然也可以通过公私钥的方式配置免密登录,这里我先用暗码了。安装openssh的时候看提示应该就已经天生了公钥,目次是$PREFIX/etc/shh,然后就和linux免密登录一样了。
$PREFIX这个变量是termux界说的,它类似于linux的根目次,比如linux的/etc目次在termux里就是指$PREFIX/etc,这在后面的docker换源时会用到。
sshd启动的默认端口是8022,我的用户名是u0_a140,在cmd下使用ssh -p 8022 u0_a140@192.168.31.248就能毗连了,也可以使用xshell这些工具毗连。
切换pkg源
输入termux-change-repo,选择第二个按空格回车,会蓝屏一会(应该还是网络原因,很慢),等待出现源选择,然后空格勾选阿里的源
先挂载cgroup
需要安装pkg install sudo,并且用kernelsu给termux root权限,不清晰和下面的root-repo包有什么区别
sudo mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
这个每次重启都需要执行一遍
运行docker
pkg install root-repo && pkg install docker 安装root和docker
这时候需要先配置一下docker源,否则拉取不了镜像
pkg install vim
mkdir -p /data/data/com.termux/files/usr/etc/docker
vim /data/data/com.termux/files/usr/etc/docker/daemon.json
将下面的内容加到这个文件里,记得前面要加个英文逗号
- "registry-mirrors": [
- "https://hub.uuuadc.top",
- "https://docker.anyhub.us.kg",
- "https://dockerhub.jobcher.com",
- "https://dockerhub.icu",
- "https://docker.ckyl.me",
- "https://docker.awsl9527.cn"
- ]
复制代码
sudo dockerd --iptables=false 运行docker服务
sudo docker run hello-world
这时候启动docker容器会报错,
- docker: Error response from daemon: failed to create task for container: failed to start shim: start failed: io.containerd.runc.v2: create new shim socket: listen unix /data/data/com.termux/files/usr/var/run/containerd/s/fca432b16f1e32bdfce67923b7e94f3ab7f741783e5032a938bd6869d8b6d3af: bind: invalid argument: exit status 1: unknown.
复制代码
这里并不清晰什么原因,但偶然记得之前在酷安上看到一个东西,过去翻了翻[2],说是要降级containerd包的版本。先查察下containerd包的版本:
然后下载帖子里这个包,用adb传到手机上(xftp也可以),然后使用dpkg -i containerd_1.6.21-1_aarch64.deb安装
接着查察版本apt show containerd -a就看到已经安装上了
然后重新启动sudo dockerd --iptables=false,在跑hello-world容器就正常了
试了下跑python也可以,那阐明可以在手机跑爬虫了:
Ubuntu镜像也是可以的:
刷机包和boot
https://github.com/kanadeblisst00/docker-in-guacamole
引用链接
- [1] https://stackoverflow.com/questions/28565640/build-kernel-with-aarch64-linux-gnu-gcc
- [2] https://www.coolapk.com/feed/51581431?shareKey=MmRlNTgxOTVmNjliNjY5M2QwMGU~&shareUid=4285440&shareFrom=com.coolapk.market_14.2.3
参考链接
- https://gist.github.com/FreddieOliveira/efe850df7ff3951cb62d74bd770dce27
- https://ivonblog.com/posts/run-docker-natively-on-android/
- https://yzddmr6.com/posts/android-run-docker/
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |