如何在容器内高效编程?

作者 | Daniel Lemire

译者 | 苏本如,责编 | 郭芮

头图 | CSDN 下载自东方IC

出品 | CSDN(ID:CSDNnews)

以下为译文:

我个人的编程环境中包括了一些服务器、笔记本电脑和台式电脑。我的服务器是在不同的时间购买和配置的,根据需求不同,它们有不同的硬件和软件配置。这些硬件的处理器不同,AMD、英特尔、Ampere和Rockchip的处理器都有。同时这些机器上安装有各种各样的Linux发行版,包括各种旧版本和新版本。在实验室技术人员帮助我做好初始设置后,基本上这些电脑所有的管理工作都是由我一人负责。

所以,最终我时常面对这样的情形:有时候我会遇到一些非常有趣的系统,这些系统都带有旧的Linux发行版,而重新安装新Linux发行版并保证它的安全并非易事。而且,即使我费尽心力地更新了我的Linux发行版,我最终也可能会得到一个与我的合作者不同的Linux发行版,使用不同的编译器等等。更不用说在同一个Linux发行版上安装多个不同的编译器是一件非常耗费时间的事。

那么,应对这种问题,你能做些什么呢?

你可以运行虚拟机。使用VirtualBox之类的工具,你可以在Windows和 macOS中运行Linux。这种方式很简单。然而,它速度很慢,而且计算的代价高昂。

你可以切换到容器,特别是Docker容器,它们的开销要少得多。Docker现在已经是云计算中无处不在的工具。作为一个简单的描述,你可以把Docker看作一个允许你在Linux中运行Linux的容器。Docker实际上是一个沙箱,但它是一个几乎可以直接在主机上运行的沙箱。与虚拟机不同,我的测试显示,在计算密集型任务中,Docker容器可以以“原生速度”(裸机速度)运行。有报道称Docker的交互速度较慢,网络连接和磁盘访问速度也较慢。但就我的用途而言,Decker能很好地满足我的要求。

当然,如果必须的话,你也可以在macOS和Windows下运行Docker容器,不过我想这样做会需要更多的开销。

容器方法的思想始终是基于系统的起始状态。比如说,你定义了你的数据库服务器需要的配置,并且每次都以这种精确的状态(配置)来启动它。这样就使得你的基础架构具有可预测性。

这听起来不是那么完美。你仍然必须依赖于你的容器的起始配置。如果两个具有不同要求的应用程序需要在同一个映像中一起运行,那么你可能需要进行各种配置操作。

话虽如此,容器仍然工作得很好,它们基本上成了维系我们当令技术文明的基础:许多基于云的应用程序都是以某种方式基于容器的。

容器的目是将软件部署到生产环境中去。在容器内编程是不被直接支持的:你将找不到关于容器编程的很多文档,而且围绕着容器编程也根本没有什么业务模型。那么这里我提到的“在容器内编程”是什么意思呢?我的意思是:我要启动一个C编程项目,决定使用Linux Ubuntu16.10发行版,并在Linux Ubuntu16.10下编译和运行我的代码,即使我的服务器可能运行完全不同的Linux发行版(或者可能在macOS下)。

第一个问题是,你的磁盘和从容器构建来的映像的磁盘是不同的。正在运行的映像无法自由访问底层服务器(主机)。记住容器本质上是一个沙箱。

因此,你只可以在映像里面做所有的工作。但是,请记住,容器技术的重点是始终从原始状态开始。如果你加载了一个图像,做了一些工作,然后离开……你的工作就不见了。映像被设计成是不可变的。这是一件很好的事情,因为这保证了你不会因为一不小心就把映像弄乱。

在映像中完成一些工作后,可以为新状态拍摄快照,提交它并创建一个新映像,再从中重新开始。这个过程既复杂又不实用。

那么你能做什么呢?你可以做的是保持映像的无状态,就像一个映像本来就应该是无状态的那样。这样的话,映像中将只能包含编译器和构建工具。因为没有理由频繁地更换这些工具。同时你将所有的代码都放在一个目录中,就像你通常所做的那样。要运行和编译代码,你可以进入映像中并运行命令。你可以在进入代码存储库时将其从主机磁盘绑定到映像。

这种方式效果更好。但是如果直接执行Docker命令行,则会出现以下问题:

1)根据你机器上的Docker配置,你可能会发现无法从映像读取或写入绑定到该映像的磁盘。对这个问题的一个快速修复方法是以特权访问方式来运行映像,但这种方法通常不受欢迎(而且不必要)。

2)从Docker映像中创建或修改的文件显示在主机磁盘上时,通常带有奇怪的文件权限。比如说,可能所有文件都属于根用户。我的一个研究助理有一个很好的变通解决办法:他一直以根用户的身份运行Linux。但是,我不推荐这样的方法。

这些小问题根源在于Docker以一种奇怪的方式来处理权限和安全性。可能与你了解的相反,设置用户和组标识符并不是一件简单的事情:在某些系统上可能足够简单,但在一些需要额外注意的支持增强的安全性的Linux系统上就不那么简单了。

最后,你需要记住很多复杂的命令。如果你和我一样,想把所有的注意力都集中在代码上,而不愿意在Docker上面浪费太多的时间。怎么办?

解决方法是使用一个小小的脚本。以我为例,我使用一个bash脚本。你可以在GitHub上找到它。它可以帮助你理清零乱的命令和文件权限。

尽管多年来,我一直试图避免依赖脚本,但是为了高效的工作,这是无可避免的。

基本上,我的做法是向我工作的目录的根目录中复制两个文件(Dockerfile和run文件),然后键入命令:

./run bash

就是这么简单!现在我进入了主机目录的一个子shell中。我可以在这里运行我的程序,编译我的代码,我对最近的Ubuntu发行版有完全的访问权限,这种方式甚至在我的基于ARM的服务器环境中也能很好地工作。

这个run脚本也可以接受其他命令,因此我可以将它作为其他脚本的一部分。

原文:https://lemire.me/blog/2020/05/22/programming-inside-a-container/

本文为 CSDN 翻译,转载请注明来源出处。

6月3日20:00,CSDN 创始人&董事长、极客帮创投创始合伙人蒋涛携手全球顶级开源基金会主席、董事,聚焦中国开源现状,直面开发者在开源技术、商业上的难题,你绝不可错过的开源巅峰对谈!立即免费围观

推荐阅读

  • 因为一个跨域请求,我差点丢了饭碗

  • 没错,你离分布式搜索只差一个Elasticsearch入门!

  • Python开发之:Django基于Docker实现Mysql数据库读写分离、集群、主从同步详解 | 原力计划

  • 全球Python调查报告:Python 2正在消亡,PyCharm比VS Code更受欢迎

  • 无代码来了,还要程序员吗?

  • 再见,Eclipse | 原力计划

  • 区块链共识算法总结 | 原力计划

真香,朕在看了!

你可能感兴趣的:(如何在容器内高效编程?)