写完新功能,本地测试全过,一上生产环境就崩溃——"我这明明能跑啊!"这种崩溃每位程序员都经历过。容器技术最初就是为了解决这个经典难题:把你的"机器"整个打包带走,让代码在任何地方表现一致。

但容器到底是什么?多数人直觉上觉得它是某种复杂的虚拟机,在电脑里模拟另一台电脑。作者曾在Pivotal/VMware参与容器开发数月,脑子里也是这个画面——但这其实是个误解。

打开网易新闻 查看精彩图片

真相简单得多:容器就是你电脑上的一个普通目录,里面跑着一个进程。让它成为"容器"而非普通进程的秘诀,是借助Linux内核的一些内置特性,"欺骗"这个进程,让它以为这个目录就是整台计算机。在这个进程眼里,目录之外空无一物,这片天地就是它的全部宇宙。

本文是两部曲的第一部分,将用60行Go代码从零实现Docker的核心机制,揭开这层"幻觉"的面纱。由于容器深度依赖Linux内核,教程需在Linux环境运行;Mac用户需先启动Linux虚拟机,因为Darwin内核不支持这些系统调用。

选用Go语言是因为它能极其简洁地调用底层Linux系统调用——这也是Docker、Kubernetes等云原生项目普遍采用Go的原因。我们要复现的核心行为是这条常见命令的效果:

docker run -it ubuntu /bin/bash

执行后会进入一个新shell,与宿主机完全隔离。几个明显特征:提示符从[用户名]@[主机名]变成root@[随机字符串];执行hostname命令,容器内返回的是Docker分配的假主机名,而非真实计算机名称。