容器内的编程

2020-05-23 02:57:15

我有少量的服务器、笔记本电脑和台式机。我的服务器是在不同的时间购买和配置的。根据设计,它们具有不同的硬件和软件配置。我有AMD、英特尔、安培和RockChip的处理器。我有各种各样的Linux发行版,既有旧的,也有新的。我也主要是自己管理所有的事情,在实验室技术人员的一些帮助下进行初始设置。

最终的结果是,我有时会得到非常有趣的系统,这些系统承载着旧的Linux发行版。重新安装Linux并保证其安全是很困难的。此外,即使我仔细更新我的Linux发行版,我最终可能会得到一个与我的合作者不同的Linux发行版,使用不同的编译器等等。在同一个Linux发行版上安装多个不同的编译器非常耗时。

我可以运行虚拟机。有了像VirtualBox这样的东西,你就可以在Windows insider MacOS中运行Linux。很漂亮。但它也很慢,计算成本也很高。

您可以切换到容器,特别是Docker,它们的开销要小得多。Docker是云计算中无处不在的工具。总而言之,Docker允许您在Linux内部运行Linux。它是一个沙箱,但是几乎直接在主机上运行的沙箱。与虚拟机不同,我的测试显示,在计算密集型任务中,Docker容器以“本机速度”(裸机)运行。有报道称,系统交互速度较慢。网络连接和磁盘访问速度较慢。对我来说,这很好。

如果必须的话,你也可以在MacOS和Windows上运行Docker,不过我想那样会有更多的开销。

容器方法的思想是始终从原始状态开始。因此,您定义数据库服务器所需的配置,并在每次启动它时都处于这种精确的状态。这使您的基础设施具有可预测性。

它并不像听起来那么完美。您仍然严重依赖于您开始使用的容器的质量。如果您需要两个具有不同要求的应用程序在同一映像中一起运行,则可能需要各种黑客攻击。

尽管如此,容器工作得足够好,基本上维持了我们的文明:许多基于云的应用程序都以某种方式基于容器。

容器是用来将软件部署到生产中的。不直接支持容器内的编程:您找不到太多关于它的文档,也没有关于它的业务模型。我所说的“在容器内编程”是什么意思?我的意思是,我将开始一个C编程项目,决定我将使用Linux Ubuntu 16.10发行版,并且我将在Linux Ubuntu 16.10下编译和运行我的代码,即使我的服务器可能运行完全不同的Linux发行版(或者可能在MacOS下)。

第一个问题是,您的磁盘和从容器构建的映像的磁盘是不同的。正在运行的映像不能自由访问底层服务器(主机)。请记住,这是一个沙箱。

这样您就可以在图像中完成所有工作。但是,请记住,容器技术的要点是始终从原始状态开始。如果您加载了一个图像,请做一些工作,然后离开…。你的工作没了。图像在设计上是不可变的。这是一件很棒的事情:你不能因为不小心修修补补就轻易搞砸了一张图片。

在映像中做了一些工作之后,您可以拍摄新状态的快照,提交它,然后创建一个新映像,您可以从该映像重新开始。这很复杂,而且不实用。

你还能做什么呢?相反,您可以做的是使映像保持无状态,因为映像应该是无状态的。该映像将仅包含编译器和生成工具。没有理由更改这些工具中的任何一个。您将像往常一样将所有代码放在一个目录中。要运行和编译代码,您需要输入映像并运行命令。您可以在进入时将存储库从主机磁盘绑定到映像。

这样效果要好得多,但如果您直接发出docker命令行,则会出现故障:

根据您机器上Docker的配置情况,您可能会发现无法从镜像中读写与镜像绑定的磁盘。一种快速修复方法是以特权访问方式运行映像,但通常不会对此表示不满(而且没有必要)。

您在Docker镜像中创建或修改的文件将出现在主机磁盘上,通常具有陌生的文件权限。例如,可能所有文件都归root用户所有。我有一个研究助理,他有一个很好的变通办法:他一直以root身份运行Linux。我不建议这样的策略。

这些故障来自Docker处理权限和安全性的奇怪方式。与您的意思相反,阅读,这不是设置用户和组标识符的简单问题:在某些系统上可能足够了,但在支持安全增强的Linux的系统上则不够,因为这些系统需要额外的注意。

最后,你需要记住很多复杂的命令。如果你和我有什么相似之处,你宁可不去想多克。您希望将所有注意力都集中在代码上。

因此,解决方案是使用一个小脚本。在我的例子中,我使用bash脚本。你可以在GitHub上找到它。它为您处理杂乱无章的命令和文件权限。

多年来,我试图避免不得不依赖脚本,但要高效地工作是不可避免的。

基本上,我在要工作的目录(Dockerfile和Run)的根目录下复制两个文件,然后键入:

仅此而已。我现在在主机目录内的一个子shell中。我可以运行程序,编译它们。我可以完全访问最近的Ubuntu发行版。即使在我拥有的基于ARM的服务器上也可以使用。

运行脚本还可以接受其他命令,因此我可以将其用作其他脚本的一部分。

混合绑定到同一编程目录的不同映像或混合使用主机构建工具和映像构建工具是不安全的。具体地说,由映像创建的二进制文件只能在映像内部运行。因此,如果您希望使用多个不同的映像进行编程,则可能需要复制这些目录。

映像不知道主机目录的实际位置。这意味着错误消息将与主机文件路径不同步。我很想解决这个特别的问题,但我不知道如何才能不引入额外的复杂性。