Docker 很奇怪
我决定随便做一个自己的容器运行时,尽管我仍然处于早期阶段,但我发现 Docker 很奇怪。这是我关于 Docker 学到的一些奇怪的事情。容器并不真实。与虚拟机不同,容器只是具有特殊限制的进程。你的内核仍然在运行那个进程!如果你知道去哪里找,你甚至可以在 /proc 中找到那个进程。容器真的不真实。实际上,没有一个 Linux 特性就是“容器”。相反,容器实际上是 5 个不同的 Linux 内核特性的组合。命名空间隐藏了主机和容器可以看到的内容,cgroups 限制容器的资源使用,还有一整套我不理解的网络魔法,让你能够隔离一个容器的网络。镜像只是文件夹。镜像只是 Docker 在某处放置的文件夹,然后调用 chroot(或 pivot_root)以使该文件夹成为你的容器进程的新根目录。因此,如果你运行 docker run -it --rm ubuntu /bin/bash,Docker 将会:从 Dockerhub 下载 ubuntu 镜像。将该镜像放在某处。运行 /some/weird/docker/path/bin/bash。Go 在容器运行时中有点糟糕。Docker 的容器运行时 runc 是用 Go 编写的,而 Go 有一些设计选择让其不太适合容器运行时。Go 的运行时是本地多线程的。这是一个非常酷的特性,但在 runc 中会带来一些挑战。许多容器运行时需要调用的 Linux 系统调用必须在单线程环境中完成,因此 runc 有一个疯狂的 C 模块,在 Go 的运行时初始化之前运行,以便它可以运行那些系统调用。Go 也没有 fork!Fork 只会分叉主线程,因此在像 Go 这样的运行时中,它算是一种隐患。但容器运行时确实想要分叉,设置一堆限制,然后执行你实际放入 docker run 的进程。为了解决这个问题,runc 以特殊命令行参数 execs /proc/self/exe,标识它为子进程,以模拟 fork。Docker 需要 root!如果你像我一样在 MacOS 上运行 Docker,这一点很容易被忽视。容器运行时使用的许多 Linux 内核 API 都要求,或者至少曾经要求,以 root 身份运行,因此 Docker 守护进程通常以 root 身份运行。我只能想象容器安全是一项非常艰巨的工作。现在看来要好一些。一个很大的例外似乎是网络。如果你正在运行无 root 的容器运行时,听起来像是必须在用户空间重新实现整个网络堆栈,以实际上给你相同的功能!学习很有趣!我才刚开始自己的容器运行时,我已经觉得我对 Docker 学到了很多。编写你使用的工具的自己的版本是了解它的一个好方法!
阅读全文 →本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡