作者 | Damian Perera
编译 | 火火酱,责编 | Carol
出品 | CSDN云计算(ID:CSDNcloud)
自从Docker在2013年初上线以来,就与程序员及系统管理员之间产生了一种爱恨交加的奇妙关系。虽然与我交谈过的一些经验丰富的的开发人员都非常不喜欢容器化(稍后会详细介绍),但是为什么许多大公司,包括eBay、Twitter、Spotify和Lyft在内,都在他们的生产环境中采用了Docker呢?
Docker究竟是做什么的呢?
不知道您是否曾使用过VMware、VirtualBox、Parallels或任何其他的虚拟化软件呢?Docker和这些软件差不多(尽管没有花哨的GUI),它能创建出带有操作系统的虚拟机,并且可以绑定选定的web应用程序及其依赖项。
虚拟机的速度不是很慢吗?
虚拟化推动了云计算革命,我喜欢把Docker称为虚拟化的最后一步,因为实际上,它执行着的正是您开发出来的业务逻辑。
但是,通常意义上真正的虚拟机的速度是很慢的,而且,并不能将Docker所做的工作完全归类于虚拟化。
相反,Docker通过使用runc(由Open Containers Initiative提供维护)在内核(对不同进程命名空间和设备命名空间提供的)支持的基础上建立额外的抽象层,从而能够共享很多主机系统的资源。因为在Docker容器和主机内核之间没有额外的虚拟化层,所以容器能够提供与主机相同的性能。
runc:
https://github.com/opencontainers/runc
Open Containers Initiative:
https://www.opencontainers.org/
完全虚拟化的系统会为其分配自己的资源,并且进行最小化程度的共享(如果需要的话),这会导致更多资源之间的隔离,但系统也会变得需要更多资源——然而,通过Docker,资源的隔离会减少,同时容器也会变得轻量级(需要的资源更少)。
如果您要运行一个需要在保证资源的基础上完全隔离的系统(例如,游戏服务器),那么或许该选择基于KVM或OpenVZ的虚拟机。但是,如果您只是想要将各个进程隔离开来,将其运行在一个大小适中的主机上,同时又不致力于把自己搞破产,那么Docker将会是您的不二选择。
如果您想了解更多关于运行容器化系统的性能方面的信息,可以看看这一篇来自IBM的研究论文:《虚拟机和Linux容器的最新性能比较(An Updated Performance Comparison of Virtual Machines and Linux Containers)》,该论文很好地比较了虚拟机和容器。
论文链接:
http://domino.research.ibm.com/library/cyberdig.nsf/papers/0929052195DD819C85257D2300681E7B/$File/rc25482.pdf
不能直接将应用程序上传到云服务器上吗?
如果不在意基础设施、环境一致性、可扩展性或可用性这类东西的话,是可以这样做的。
设想一下:您管理着12个Java服务,并将它们全部部署到了运行着Ubuntu和Java 8的独立服务器上,以用于开发、质量保证、预发布及生产环境。即使您应用程序的使用程度并不高,也需要管理至少48个服务器(12个服务*4个环境)。
假设现在需要您的团队带头更改策略,将运行环境升级到Java 11。那么您需要登录并手动更新48个服务器。即使是使用Chef或Puppet这类的工具,工作量也非常大。
有什么更简便的解决方案呢?
Docker能够帮助您创建所需操作系统的快照,并只在其上安装所需的依赖项。这样一来,您可以管理或省去所有的“臃肿软件”。您可以最小化安装Linux(我推荐Alpine Linux,但在本文中,我将继续使用Ubuntu),并且只在上面安装Java 8。
在需要更新时,只需要在您Java映像的Dockerfile文件中说明使用Java 11,构建并推送到容器存储库(如Docker Hub或Amazon ECR)中。此后,您只需修改您的应用程序容器基础镜像标签,引用新的快照并重新部署即可。
以下示例罗列了在Ubuntu 18.04最小操作系统之上构建Docker容器的要点:
我将使用标签oracle-jdk-ubuntu-18.04:1.8.0_191来构建此映像并将其推送至Docker Hub账户damian, 然后用它来为我的服务构建另一个容器:
# Instructs Docker to build this container on top of this snapshot
FROM damian/oracle-jdk-ubuntu-18.04:1.8.0_191
# Copys the application JAR to the container
COPY build/hello-world.jar hello-world.jar
# Executes this command when the container starts
CMD java -jar hello-world.jar
现在,如果我需要将服务更新到Java 11,那么需要做的只是:发布安装了兼容JRE的Java快照新版本,在服务容器中的FROM声明中更新标签,令容器使用新的基础映像。完成!接下来,您的所有服务都会随着Ubuntu和Java的更新而更新。
但是这对我的开发来说有什么意义呢?
这是个好问题。
我最近开始在单元测试中使用Docker。假设您有成千上万的测试用例(如果真是这样的话,相信我,我对您的痛苦感同身受),这些用例都连接到一个数据库,其中每个测试类都需要一个数据库的新副本,并且每个测试用例都将对数据执行CRUD操作。
通常来讲,在每次测试之后,都需要使用类似Redgate的Flyway之类的工具来重置数据库,但是这就意味着您的测试必须按顺序运行,该过程会花费很多时间(我见过要因此而花20分钟才能完成的单元测试套件)。
在Docker中,您可以轻松地创建您数据库的映像(我建议使用TestContainers),在容器中为每个测试类运行一个数据库实例,然后并行运行整个测试套件。因为所有测试类都是并行运行的,并且都链接单独的数据库,所以它们都可以同时在同一主机上运行并且快速完成(假设您的CPU能扛住的话)。
我在用Golang编码时也会使用Docker。与其直接在开发机器上安装GO,我更喜欢采用类似于Konstantin Darutkin的方法:通过安装Go和依赖项来维护Dockerfile文件,可以将其配置为在对源文件进行修改时实时重新加载项目。
这样一来,我已经有了自己的项目和Dockerfile版本控制文件,如果我要修改自己的开发机器或将其格式化,我只需要重新安装Docker,从上次停留的地方继续就可以了。
总结
如果您经营着一家初创公司,还没有决定要用什么来支撑您的新技术栈,又或者您是一家成熟的服务提供商,正在考虑将您的产品和非产品环境容器化,但又不敢在“未经测试的”海域上航行,那么可以考虑以下的几个问题。
1、一致性
您可能有整个行业中最棒的一群开发人员,但是在所有这些不同的操作系统中,每个人都有自己喜欢的设置方式。如果您已经用Docker配置了完善的本地环境,那么新开发人员只需安装,用该应用程序生成一个容器,然后启动即可。
2、调试
您可以轻松地隔离并消除整个团队环境中的问题,而无需了解团队成员计算机的设置方式。一个很好的应用实例是:当我们必须通过从ntpd迁移到Chrony来修复服务器上的一些时间同步问题时,我们只需要更新基础映像(不需要通知开发团队)。
3、自动化
目前,包括Jenkins、CircleCI、TravisCI等在内的大部分CI/CD工具都被完全集成到了Docker中,因此您可以轻松地将从一个环境应用到另一个环境。
4、云端支持
要想了解您的服务器和DataDog上运行着什么,就需要持续监视和控制容器。一家云监视公司曾说道:
容器的短寿命和密度增加对基础设施的监控具有重要意义。它们代表需要单独监视的事物数量的数量级增加。
自我管理的云编排工具(例如,Docker Swarm和Kubernetes)以及由供应商管理的工具(例如,AWS的Elastic Container Service和Google Kubernetes Engine)提供了针对这一问题的解决方案,这些工具可以监视和管理容器集群和调度。
随着Docker的广泛使用以及与AWS和Google Cloud等云服务提供商的紧密集成,Docker正在迅速成为处理您新应用程序或现有应用程序的明智之选。
原文:https://hackernoon.com/an-introduction-to-docker-and-how-it-is-important-for-sysadmins-9ai83awo
本文为CSDN 云计算翻译,未经授权请勿转载。
RECOMMEND
推荐阅读
适读人群 :1.云计算开发人员。2.网络应用开发与管理人员。
入门Docker的首本书,经典畅销书升级,系统化掌握容器技术栈,第3版基于 Docker 新 18.x 系列版本。
长按下方二维码
发现更多好书
在看点一下