前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Docker与容器

Docker与容器

作者头像
啃饼思录
发布2020-10-23 11:14:35
4180
发布2020-10-23 11:14:35
举报

Docker与容器

从19年初开始使用Docker到现在差不到两年了,感觉对于Docker的认识还停留在使用的阶段,各个知识点串联度不够,没有形成一个体系,因此打算抽出一些时间来系统学习Docker,以便在后续使用的时候更加得心应手。

写在前面

本篇首先学习Docker是什么,之后会剖析Docker和相关容器技术,以及它在DevOps等运用场景所带来的巨大便利,最后学习Docker在整个虚拟化领域中的技术定位。

虚拟技术

我们知道在主机时代比拼的是单个服务器的性能,如CPU主频和内存的强弱,而在云时代,最为看中的则是凭借虚拟化技术所构建的集群处理能力。从传统来看,虚拟化既可以通过硬件模拟来实现,也可以通过操作系统软件来实现。而容器技术则更优雅,它充分利用了操作系统本身已有的机制和特性,可以实现远超虚拟机的轻量级虚拟化。因此有人甚至将其称为“新一代的虚拟化”技术,并将基于容器打造的云平台亲切的称为“容器云”。

什么是Docker

Docker是基于Go语言开发的开源容器项目,它诞生于2013年。现在主流的操作系统包括Linux的各大发行版、macOS、Windows等都已经支持Docker。

Docker的构想是要实现“Build,Ship and Run Any App,Anywhere”,即通过对应用的封装(Packing)、分发(Distribution)、部署(Deployment)、运行(Runtime)生命周期进行管理,达到应用组件级别的“一次封装,到处运行”。请注意这里的应用组件可以是一个Web应用,一个编译环境,也可以是一套数据库平台服务,甚至是一个操作系统或集群。

基于Linux平台的多项开源技术,Docker提供了高效、敏捷和轻量级的容器方案,并支持部署到本地环境和多种主流云平台。可以说Docker首次为应用的开发、运行和部署提供了“一站式”的实用解决方案。

Linux容器技术

Linux容器技术,即Linux Containers(LXC)技术,IBM DeveloperWorks网站关于容器技术的描述十分准确:“容器有效的将单个操作系统管理的资源划分到孤立的组中,以更好的在孤立的组之间平衡有冲突的资源使用需求。与虚拟化相比,这样既不需要指令级模拟,也不需要即时编译。容器可以在核心CPU本地运行指令,而不需要任何专门的解释机制。此外,也避免了准虚拟化和系统调用替换中的负载性。”

LXC经历了长期的演化,并集成到主流的Linux内核中,进而成为Linux系统轻量级容器技术的实施标准。

从Linux容器到Docker

在LXC的基础上,Docker进一步优化了容器的使用体验,使其变得大众化。首先,Docker提供了各种容器管理工具(如分发、版本、移植等),让用户无需关注底层的操作,更加简单明了的管理和使用容器:其次,Docker通过引入分层文件系统构建和高效的镜像机制,降低了迁移难度,极大的改善了用户体验,这使得用户操作Docker容器就像操作应用自身一样简单。

通俗的讲,我们可以将Docker容器理解为一种轻量级的沙盒(sandbox)。每个容器内运行着一个应用,不同的容器相互隔离,容器之间也可以通过网络互相通信。容器的创建和停止十分迅速,几乎跟创建和终止原生应用一致;此外容器自身对于系统资源的额外需求也十分有限,远远低于传统的虚拟机。在很多时候,直接将容器当做应用本身也没有任何问题。

使用Docker的原因

Docker容器虚拟化的好处

Docker项目的发起人,Docker公司的CTO认为Docker在正确的地点、正确的时间顺应了正确的趋势---如何正确地构建应用。

我们知道在云时代,开发者创建的应用必须要能很方便的在网络上传播,也就是说应用必须脱离底层物理硬件的限制;同时还必须是“任何时间任何地点”都可以获取到的。因此我们需要一种新型的创建分布式应用程序的方式,快速分发和部署,而这些正是Docker所能提供的最大优势。

举个简单的例子,假设用户视图采用最常见的LAMP(Linux+Apache+Mysql+PHP)组合来构建网站。那么按照传统的做法,首先需要安装Apache、Mysql+PHP以及它们各自所依赖的环境;之后分别对它们进行配置(包括创建合适的用户、配置参数等);经过大量的操作后,还需要进行功能测试,看看是否工作正常;如果不正常还需要进行调式追踪,这就意味着需要花费更多的时间和可能出现一些不可控的风险。如果应用数目变多,那么事情则会变得更加难以处理。

上面倒还好说,假如一旦需要服务器迁移,如从亚马逊迁移到其他云,那么往往需要对每个应用都进行重新部署和调式。这些都是重复性的“体力活”,极大的降低了用户的工作效率。究其根源,是这些应用直接运行在底层操作系统上,无法保证同一份应用在不同的环境中行为一致。

鉴于此种情况,Docker提供了一种更为“聪明”的方式,通过容器来打包应用、解耦应用和运行平台。这也就意味着迁移的时候,只需在新的服务器上启动需要的容器即可,根本不用去理会服务器是否是同一平台等问题。毫无疑问这极大的简化了部署的流程,降低了部署过程中出现问题的风险,最重要的是节省了大量的时间。

Docker在开发和运维中的优势

由于笔者做过运维开发,因此对于Docker在开发和运维中的优势是最能切身感受到的。对于运维开发人员来说,最希望的是一次创建或者配置某个环境后可以做到在任意时间,任意地点让应用能正常运行,而Docker做到了这一点,因此深受广大运维人员的青睐。

总结起来有以下几个方面的优势:

「(1)更快速的交付和部署。」 使用Docker,开发人员可以使用镜像来快速构建一套标准的开发环境;开发完成后,测试和运维人员可以直接使用完全相同的环境来部署代码。这样只要是开发测试过的代码,就可以确保在生产环境中无缝运行。Docker可以快速创建和删除容器,实现快速迭代、节约开发、测试、部署的大量时间,且整个过程全程可见,使团队更容易理解应用的创建和工作过程。

「(2)更高效的资源利用。」 运行Docker容器不需要额外的虚拟化管理程序( Virtual Machine Manager,VMM,以及Hypervisor)的支持,Docker是内核级的虚拟化,可以实现更高的性能,同时对资源的额外需求很低。与传统虚拟机方式相比, Docker的性能要提高1~2个数量级。

「(3)更轻松的迁移和扩展。」 Docker容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等,同时支持主流的操作系统发行版本。这种兼容性让用户可以在不同平台之间轻松地迁移应用。

「(4)更简单的更新管理。」 使用Dockerfile,只需要小小的配置修改,就能替代以往大量的更新工作。所有修改都以增量的方式被分发和更新,从而实现自动化且高效的容器管理。

Docker与虚拟机比较

Docker作为一种轻量级的虚拟方式,经常用来和传统的虚拟机方式进行对比,这是一个老生常谈的话题,笔者就选择其中的4点进行介绍:

(1)Docker容器很快,启动和停止可以在秒级实现,而传统的虚拟机则少至几分钟,长则半个小时;

(2)Docker容器对于系统资源的需求很少,一台主机可以同时运行上千个Docker容器,据说在IBM服务器上已经实现了同时运行一万个容器实例的可能;但是一台主机最多只能运行8个传统的虚拟机(这已经是性能不错的主机了,笔者电脑似乎运行3个就到头了);

(3)Docker借鉴了Git的设计理念来方便用户获取、分发和更新应用镜像,存储复用,增量更新;

(4)Docker通过Dockerfile支持灵活的自动化创建和部署机制,以提高工作效率,并标准化流程。

关于Docker和传统虚拟机技术的对比,可以看如下表格:

特性

容器

虚拟机

启动速度

秒级

分钟级

性能

接近原生

较差

内存代价

较小

较多

硬盘使用

MB级别

GB级别

运行密度

单机支持上千个容器

一般几十个

隔离性

安全隔离

完全隔离

迁移性

优秀

一般

Docker容器除了运行其中的应用外,基本不消耗额外的系统资源,这样在保证应用性能的同时可以减少系统的开销。

传统的虚拟机如果想运行N个不同的应用,就需要启动N个虚拟机,因为开发者需要为每个虚拟机单独分配独占的内存、磁盘等资源;Docker只需启动N个隔离的容器,然后将应用放进容器即可,这样使得应用可以获得接近于原生的运行性能。

这里需要着重提一下Docker的隔离性,我们知道传统的虚拟机方式采用的是相对封闭的隔离,即操作系统层面是不互通的;而Docker则利用了Linux系统上的多种防护技术实现了严格的隔离,且可以整合众多安全工具。

Docker虚拟机也称轻量级虚拟机,原因在于这些容器中所运行的Linux系统并不是一个独立完整的Linux系统,这些容器其实是共用了一个Linux内核,也就是Docker系统为它们提供的Linux内核。

Docker与虚拟化

虚拟化技术在各个行业都有,在计算机领域一般是指计算虚拟化或者服务虚拟化。这里援引维基百科的解释:

  • 虚拟化:在计算机技术中,虚拟化是一种资源管理技术,是将计算机

也就是说,虚拟化的核心是对资源进行抽象,其目的是为了在同一个主机上同时运行多个系统或者应用,进而提高系统资源的利用率,同时能降低成本,便于管理和带来容错容灾功能。

一般来说,虚拟化技术分为硬件虚拟化和软件虚拟化,其中基于硬件的虚拟化技术不多,如网卡中的单根多IO虚拟化,这种比较深奥,笔者觉得目前还没有到学习它的必要;而基于软件的虚拟化技术则是日常使用最多的,它根据软件虚拟化对象所在的层次,可以划分为应用虚拟化和平台虚拟化(通常所说的虚拟机技术指的就是这个)。

应用虚拟化一般是一些模拟设备或者诸如Wine这样的软件;平台虚拟化可以细分为几个子类:「(1)完全虚拟化。」 虚拟机模拟完整的底层硬件环境和特权指令的执行过程,客户端操作系统无须进行修改。如VMware Workstation,VirtualBox,QEMU等。

「(2)硬件辅助虚拟化。」 利用硬件(主要是CPU)辅助支持(目前x86体系结构上可用的硬件辅助虚拟化技术包括Intel-VT和AMD-V)处理敏感指令来实现完全虚拟化的功能,客户端操作系统无效修改,如VMware Workstation,Xen和KVM。

「(3)部分虚拟化。」 只针对部分硬件资源进行虚拟化,这样使得客户端操作系统需要进行修改。

「(4)超虚拟化。」 部分硬件接口以软件的形式提供为客户机操作系统,客户操作系统需要进行修改,如早期的Xen。

「(5)操作系统级虚拟化」。内核通过创建多个虚拟的操作系统实例(内核和库)来隔离不同的进程。前面介绍的容器技术就属于这个范畴。

也就是说Docker以及其他的容器技术都属于操作系统级虚拟化这个范畴,操作系统虚拟化最大的特点就是不需要额外的supervisor支持。Docker虚拟化方式之所以有如此多的优势,这与操作系统虚拟化技术自身的设计和实现是分不开的:

从上图可以看到,左侧的传统的虚拟化方式是在硬件层面实现虚拟化,需要有额外的虚拟机管理应用和虚拟机操作系统层。而右侧的Docker容器则是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,因此占用资源非常少,属于轻量级。

Docker核心概念

前面都是一些比较基础的知识,学习它对于Docker的设计思想会有更深的理解。接下来开始学习Docker中的三大核心概念:镜像、容器和仓库,只有理解了这三个概念才能对Docker容器的整个生命周期有一个较为清晰的认识。

Docker镜像

Docker镜像(Image)类似于虚拟机镜像,如常见的iso格式的系统镜像,你可以将其理解为一个可读的模板,但是这又和iso镜像不同的是,通常Docker镜像中是比较纯净的,一个镜像可以包含一个基本的操作系统,里面仅仅是安装了Nginx应用程序,此时可以称其为一个Nginx镜像。

镜像是创建Docker容器的基础。通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有镜像,用户甚至可以从网上下载已经做好的镜像,并直接使用。

Docker容器

Docker容器(Container)类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。

容器是是从镜像创建的应用运行实例,镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等,容器与容器之间是彼此隔离,互不可见的。

其实你完全可以将容器当做一个简易版的Linux系统环境(包括root用户权限、进程空间、用户空间和网络空间)以及运行在其中的应用程序打包而成的盒子。

「请注意,镜像本身是只读的,容器从镜像启动的时候,会在镜像的最上层创建一个可写层。」

Docker仓库

Docker仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。

但是有的时候我们会将Docker仓库和仓库注册服务器(Register)搞混淆,其实这两者是有区别的。仓库注册服务器是存放仓库的地方,其上面往往包括多个仓库。每一个仓库都集中存放某一类镜像,因此往往会包括多个镜像文件,通过使用不同的tag标签来进行区分。

如下图所示的注册服务器,它存放着Ubuntu和CentOS的仓库,而这两个仓库又各自存放着不同版本的操作系统:

根据所储存镜像的公开分享与否,Docker仓库可以分为公开仓库(public)和私有仓库(Private)两种形式。目前最大的公开仓库是官方提供的Docker Hub,里面存放着大量的镜像,国内的很多云服务商也提供了仓库的本地源,以便于我们在国内稳定下载。当然了,Docker也支持用户在本地网络内创建一个只能自己访问的私有仓库,这样用户不希望公开分享自己镜像的时候就可以这样操作。

当用户创建了自己的镜像后,可以使用push命令将其上传到指定的公有仓库或者是私有仓库,这样当用户在下次使用的时候就可以直接从仓库上将之前的镜像给pull下拉,这一点与Git非常相似,因为Docker利用仓库管理镜像的设计理念借鉴了Git代码仓库的管理理念。

安装Docker引擎

Docker引擎是使用Docker容器的核心组件,它可以运行在主流的操作系统上,这里以CentOS安装Docker引擎为例进行介绍。首先点击 这里,访问Docker的官网来查看获取Docker的方式以及Docker支持的平台类型:

目前Docker支持Docker引擎、Docker Hub和Docker Cloud等多种服务。其中Docker引擎包括支持在桌面系统或云平台安装Docker,以及为企业提供简单安全弹性的容器集群的编排和管理;Docker Hub则是官方提供的云托管服务,可以提供公有或者私有的镜像仓库;Docker Cloud是官方提供的容器云服务,可以完成容器的部署与管理,可以完整地支持容器化项目,同时还提供了CI、CD功能。Docker引擎目前分为社区版(CE)和企业版(EE),社区版包括大部分的核心功能,因此正常情况下使用社区版即可。

第一步,使用uname -a命令来查看当前CentOS的内核版本,Docker官方强调至少3.8以上,建议使用3.10及以上内核:

代码语言:javascript
复制
[root@localhost ~]# uname -a
Linux localhost.localdomain 3.10.0-1062.18.1.el7.x86_64 #1 SMP Tue Mar 17 23:49:17 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

第二步,使用yum update命令来升级yum源,请注意切勿在生产环境中升级yum源,因为更新命令会对软件包和内核升级。

第三步,安装需要的软件包,主要是yum-utils、device-mapper-persistent-data和lvm2包,其中yum-utils提供yum-config-manager功能,另外两个是devicemapper驱动依赖的,即便于后续支持devicemapper类型:

代码语言:javascript
复制
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm2

第四步,设置yum源,操作如下:

代码语言:javascript
复制
[root@localhost ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

第五步,查看所有仓库中所有的docker版本,并选择特定版本安装:

代码语言:javascript
复制
[root@localhost ~]# yum list docker-ce --showduplicates | sort -r

第六步,安装Docker,由于repo中默认只开启stable仓库,因此使用yum install docker-ce命令安装的Docker版本是最新版本,即

代码语言:javascript
复制
[root@localhost ~]# yum install docker-ce

第七步,启动Docker和添加为开启自启动:

代码语言:javascript
复制
[root@localhost ~]# systemctl start docker
[root@localhost ~]# systemctl enable docker

第八步,检查安装是否成功(注意client和service这两部分都有,则说明安装成功),可以使用docker version命令来进行验证,如下所示:

请注意第七步和第八步的顺序不能颠倒,否则使用docker version命令时,只会显示Client的信息:

这样我们就完成了docker-ce-19.03.13版本的安装,可以看到Docker的安装还是较为简单的。

配置镜像下载地址

由于docker是在国外,因此镜像下载速度可能不太快,建议使用国内仓库,如DaoCloud。点击这里 DaoCloud,选择加速器:

然后将下面的代码直接放在shell环境中执行:

代码语言:javascript
复制
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io

执行结果如下所示:

配置Docker服务

一般来说使用Docker的用户不一定都是root用户,因此为了避免每次使用Docker命令时都需要切换到root用户,可以将当前用户加入安装自动创建的docker用户组,使用的命令如下:

代码语言:javascript
复制
sudo usermod -aG docker USER_NAME

其中的USER_NAME就是当前用户名称,然后退出并重新登录即可。

当开发者在前面设置了docker开机自启动服务时,使用ps -aux|grep docker命令来查看docker是否正在运行时,结果如下所示:

代码语言:javascript
复制
[envythink@localhost ~]$ ps -aux|grep docker
root       1208  0.6  3.9 830056 73384 ?        Ssl  22:32   0:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root       1802  0.0  0.0 112824   980 pts/0    S+   22:33   0:00 grep --color=auto docker

你会发现docker服务启动时,实际上调用了dockerd命令,它支持多种启动参数,所以开发者完全可以直接通过执行dockerd命令来启动docker服务,可以使用下面的命令来启动docker服务,开启Debug模式,并监听在本地的2376端口:

代码语言:javascript
复制
[envythink@localhost ~]$ dockerd -D -H tcp://127.0.0.1:2376

当然这些选项是可以写在/etc/docker/daemon.json文件中的,然后由dockerd服务启动时读取:

代码语言:javascript
复制
{
    "debug": true,
    "hosts": ["tcp://127.0.0.1:2376"]
}

对于CentOS和RedHat系统来说,服务通过systemd来管理,配置文件路径为/etc/systemd/system/docker.service.d/docker.conf,当配置发生更新后,需要通过systemctl命令老管理Docker服务,使用的命令如下:

代码语言:javascript
复制
[envythink@localhost ~]$ systemctl daemon-reload
[envythink@localhost ~]$ systemctl start docker.service

如果服务不能正常工作,可以查看Docker服务的日志文件来确定问题,可以使用journalctl -u docker.service命令来进行查看。同时每次重启Docker服务后,可以通过使用docker info命令来查看Docker信息,以确保服务已经正常运行。

小结

本篇学习了虚拟技术、Docker、容器技术、Docker的安装与三个核心概念:镜像、容器、仓库,在后面我们会围绕这三个核心概念来学习Docker的各种操作命令。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 啃饼思录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 虚拟技术
  • 什么是Docker
  • Linux容器技术
  • 从Linux容器到Docker
  • 使用Docker的原因
    • Docker容器虚拟化的好处
      • Docker在开发和运维中的优势
        • Docker与虚拟机比较
          • Docker与虚拟化
          • Docker核心概念
            • Docker镜像
              • Docker容器
                • Docker仓库
                  • 安装Docker引擎
                    • 小结
                    相关产品与服务
                    容器镜像服务
                    容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档