Skip to main content

ChromeOS 裸跑 Docker

· One min read

如果你拥有一个运行良好的ChromeOS,如果你在寻找在没有任何容器或虚拟机的帮助下运行docker的方法,那就是这篇教程。 注意:即使你通过本教程的方法成功启动了dockerd和容器,也并不代表它会如你预期的一样运行,我强烈建议你使用Debian等一般发行版运行dockerd 本文以brunch安装的ChromeOS为例,希望本文更多的是为你提供思路而非方法。

Q&A#

  • 本文讨论的环境是什么:ChromeOS及其衍生版本的系统命令行(即通过crosh进入的命令行),而非crostini、crouton等通过不同技术实现的容器环境。
  • 为什么需要在这种环境中运行dockerd:好问题
  • 什么原因使我们需要额外的操作:原因有很多,比如没有包管理器,没有systemd,没有内核支持,必须使用root用户运行,过多的文件系统限制等
  • 为什么你说dockerd而不是docker:因为我们实际需要启动的是docker daemon而不是docker cli

增加内核支持#

开启内核选项#

很遗憾在教程开头就抛出一个无法解决的问题:如果你的cros不是通过brunch安装的,也不是某些特定的衍生版本,那么你很有可能需要自行编译内核。 docker所使用的容器技术依赖于内核的namespace和cgroup支持,docker官方文档也写明了对于内核的要求:

  1. 64位操作系统
  2. 内核版本高于 3.10
  3. 系统已经正确挂载 cgroupfs

ChromeOS无法满足第三条要求,解决这个问题的方法有以下几种

  1. 使用brunch安装ChromeOS,因为brunch替换了系统的内核并且开发者已经启用了相应的内核编译选项
  2. 使用某些满足要求的衍生版本,这里不再打广告
  3. 自行编译替换内核,在编译时开启相应的编译选项

事实上这些方法都是为了在内核中开启相应功能,我并不建议你自行编译内核,而如果你有能力自行编译内核应该不需要再阅读这篇文章。

使用 cgroup v2#

经过我的测试,使用 cgroup v1 时无法正常启动dockerd,所以我们需要改为 cgroup v2,编辑引导配置,在内核启动参数中增加cgroup_no_v1=all,再次引导后ChromeOS将不会挂载cgroupfs。 在启动dockerd前挂载 cgroup 即可:

sudo mount -t cgroup2 none /sys/fs/cgroup/

你可以将这个命令写在开机脚本中或者启动dockerd的脚本中。

补足工具链#

docker官方文档中关于安装要求的另一部分就是工具链:

  • iptables 不低于1.4
  • git 不低于1.7
  • ps
  • xz 不低于4.9

你可以选择安装Chromebrewbrunch toolchain或其他方法补足工具链

fake systemctl#

这一步并非必须,但它对于我来说是一个很重要的步骤,如果你和我一样习惯于使用systemd,那么你会喜欢这一节的,或者你也可以直接跳到下一节。

Linux中有三个初始化系统最为有名:SysVinit、UpStart、Systemd。初始化系统作为系统的1号进程拥有运行时的不可替代性。ChromeOS使用的是UpStart,自行替换的可能性非常小,但docker仅支持systemd,这导致我们无法方便地管理dockerd。

docker-systemctl-replacement这个项目原本是为了解决docker容器中无法使用systemctl的问题(原因很简单,docker容器与宿主共享进程号,无论哪个容器的1号进程都是宿主的初始化系统),核心文件是由python编写的systemctl3.pyjournalctl3.py,将这两个文件下载下来并重命名放入/usr/bin即可,他们实现了部分常用参数,足够用来管理dockerd。(你可能需要修改文件中第一行的python可执行文件路径)

当然,fake systemctl并非只有这唯一的实现,类似的实现均可满足我们的需要。

docker 安装并验证#

由于没有包管理器,我选择通过直接下载二进制文件的方式安装docker,从下载站点下载最新的二进制包解压并放入/usr/bin即可。

你可以通过直接运行dockerd或者上一节提到的systemctl启动dockerd

sudo dockerd &# orsudo systemctl start docker# thensudo docker run hello-world

如果你的dockerd正常启动了,那么本文到这里就结束了。而如果你使用了我上一节提到的项目,你大概会遇到问题,因为docker-systemctl-replacement并没有提供对sock文件的支持,所以docker.service+docker.sock的配置无法使用,你可以在moby项目中找到旧的配置模板