欢迎您, 来到 宁时修博客.^_^

Docker系列1--Docker基础

2016/11/18 言则行 Docker 1031
Docker容器技术

一、Docker简介

    Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上,基于 Go 语言并遵从 Apache2.0 协议开源。

    Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 

    Docker 的基础是 Linux 容器(LXC)等技术,在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。

    下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。


  2a5.png

       394d.png



二、容器和虚拟机

    传统虚拟机如 VMware , VisualBox 之类的需要模拟包括硬件的整台机器。每台虚拟机都要有包括应用、必要的二进制和库,以及一个完整的用户操作系统,虚拟机一旦被开启,预分配给它的资源将全部被占用。


    而容器技术是和宿主机共享硬件资源及操作系统,可以实现资源的动态分配。

    容器包含应用和其所有的依赖包,与其他容器共享内核。容器在宿主机操作系统中的用户空间以隔离的进程运行。

    容器技术是实现操作系统虚拟化的一种途径,可以在资源受到隔离的进程中运行应用程序及其依赖关系。

    通过使用容器,可以轻松打包应用程序的代码、配置和依赖关系,将其变成容易使用的构建模块,从而实现环境一致性、提高运营效率、开发人员生产力和版本控制等。

    容器可以帮助保证应用程序快速、可靠、一致地部署,其间不受部署环境的影响。还赋予我们对资源更多的精细化控制能力,让基础设施效率更高。


    Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。

    Linux 容器不是模拟一个完整的操作系统,而是对进程隔离,相当于是在正常进程的外面套了一个保护层。

    对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。

    Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有Docker ,就不用担心环境问题。

    总体来说,Docker的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。



三、Docker对比传统虚拟机

    Docker优点:

    1、更快速的交付和部署。

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


    2、更高效的资源利用。

    Docker容器的运行不需要额外的虚拟化管理程序(VirtualMachine Manager,VMM,以及Hypervisor)支持,它是内核级的虚拟化,可以实现更高的性能,同时对资源的额外需求很低。跟传统虚拟机方式相比,要提高一到两个数量级。


    3、更轻松的迁移和扩展。

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


    4、更简单的更新管理。

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

 


    Docker 相比于传统虚拟化:

    1、Docker 启动快速属于秒级别。虚拟机通常需要几分钟去启动。

    2、Docker 需要的资源更少。Docker 在操作系统级别进行虚拟化,Docker 容器和内核交互,几乎没有性能损耗,性能优于通过 Hypervisor 层与内核层的虚拟化。

    3、Docker 更轻量。Docker 的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境,Docker 运行的镜像数远多于虚拟机数量,对系统的利用率非常高。

    4、与虚拟机相比,Docker 隔离性更弱。Docker 属于进程之间的隔离,虚拟机可实现系统级别隔离。

    5、安全性。Docker 的安全性也更弱,Docker 的用户 Root 和宿主机 Root 等同,一旦容器内的用户从普通用户权限提升为 Root 权限,它就直接具备了宿主机的 Root 权限,进而可进行无限制的操作。

    6、虚拟机用户 Root 权限和宿主机的 Root 权限是分离的,并且虚拟机利用如 Intel 的 VT-d 和 VT-x 的 ring-1 硬件隔离技术。

    7、这种隔离技术可以防止虚拟机突破和彼此交互,而容器至今还没有任何形式的硬件隔离,这使得容器容易受到攻击。

    8、可管理性。Docker 的集中化管理工具还不算成熟。各种虚拟化技术都有成熟的管理工具,例如 VMware vCenter 提供完备的虚拟机管理能力。

    9、高可用和可恢复性。Docker 对业务的高可用支持是通过快速重新部署实现的。

    10、虚拟化具备负载均衡,高可用,容错,迁移和数据保护等经过生产实践检验的成熟保障机制, VMware 可承诺虚拟机 99.999% 高可用,保证业务连续性。

    11、快速创建、删除。虚拟化创建是分钟级别的,Docker 容器创建是秒级别的。Docker 的快速迭代性,决定了无论是开发、测试、部署都可以节约大量时间。

    12、交付、部署。虚拟机可以通过镜像实现环境交付的一致性,但镜像分发无法体系化。Docker 在 Dockerfile 中记录了容器构建过程,可在集群中实现快速分发和快速部署。



    对比传统虚拟机:

特性容器虚拟机
启动秒级分钟级
硬盘使用一般为 MB一般为 GB
性能接近原生弱于
系统支持量单机支持上千个容器一般几十个




四、Docker的三个基本概念

    Docker 中包括三个基本的概念:

        Image(镜像)

        Container(容器)

        Repository(仓库)

    

    镜像是 Docker 运行容器的前提,仓库是存放镜像的场所,镜像是 Docker 的核心。


    1、Image(镜像)

    Docker 镜像就是一个只读的模板,是一个静态的概念。可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

    镜像不包含任何动态数据,其内容在构建之后也不会被改变。镜像(Image)就是一堆只读层(read-only layer)的统一视角,下面的这张图能够帮助理解镜像的定义:

7d553f155d.png


    左边是多个只读层,重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是 Docker 内部的实现细节,并且能够在主机的文件系统上访问到。


    统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角。这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。我们可以在图片的右边看到这个视角的形式。



    2、Container(容器)

    Docker 利用容器来运行应用程序。

    容器是从镜像创建的运行实例,是一个动态的概念。可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。

    可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

    镜像是只读的,容器在启动的时候创建一层可写层作为最上层。


    容器(Container)也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

a5.png


    实际上,容器 = 镜像 + 读写层。



    3、Repository(仓库)

    Docker 仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行。在其他服务器上使用这个镜像时,需要有一个集中存储、分发镜像的服务,Docker Registry(仓库注册服务器)就是这样的服务。

    有时候会把仓库(Repository)和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器(Registry)上往往存放着多个仓库(Repository),每个仓库中又包含了多个镜像,每个镜像有不同的标签(Tag)。


    Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。所以说,镜像仓库是 Docker 用来集中存放镜像文件的地方,类似于我们之前常用的代码仓库。

    仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

    最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。用户也可以在本地网络内创建一个私有仓库。当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以 run 了。


    一个仓库会包含同一个软件不同版本的镜像,而标签用于对应该软件的各个版本 。通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest(最新版) 作为默认标签。



五、Docker架构

    下图展示Docker的架构:

        bc95ac14.png



    Docker 使用 C/S (客户端/服务端)体系结构。Docker 客户端与 Docker 服务端进行交互,Docker服务端负责构建、运行和分发 Docker 镜像。

    Docker 客户端和服务端可以运行在一台机器上,也可以通过 RESTful 、 Stock 或网络接口与远程 Docker 服务端进行通信。

    服务端也就是docker daemon,运行在主机的后台,客户端以系统命令的形式存在,用户用docker命令来跟docker daemon 交互。在系统输入docker命令可以管理Docker的镜像、容器、网络和数据卷。


  92b030f.png



    Docker 的核心组件包括:

        Docker Client

        Docker Daemon    

        Docker Image

        Docker Registry

        Docker Container


    Docker Client

    Docker Client (Docker 客户端),其实就是 Docker 提供命令行界面(CLI)工具,是用户与 Docker服务进行交互的主要方式。

    客户端可以构建,运行和停止应用程序,可以与远程Docker主机进行交互。

    最常用的 Docker 客户端就是 docker 命令,通过 docker 命令很方便地在主机上构建、运行 Docker 容器。


    Docker Daemon

    Docker Daemon 是服务器组件,以 Linux 后台服务的方式运行,是 Docker 最核心的后台进程,也称为守护进程。

    Docker Daemon负责响应来自 Docker Client 的请求,然后将这些请求翻译成系统调用完成容器管理操作。

    该进程会在后台启动一个 API Server ,负责接收由 Docker Client 发送的请求,接收到的请求将通过 Docker Daemon 内部的一个路由分发调度,由具体的函数来执行请求。

    大致可以将其分为以下三部分:

        Docker Server

        Engine

        Job


    Docker Daemon 的架构:

    9.jpg


    Docker Daemon 通过 Docker Server 模块接受 Docker Client 的请求,并在 Engine 中处理请求,然后根据请求类型,创建出指定的 Job 并运行。 

    Docker Daemon 运行在 Docker Host 上,负责创建、运行、监控容器,构建、存储镜像。


    运行过程的作用有以下几种可能:

        向 Docker Registry 获取镜像。

        通过 GraphDriver 执行容器镜像的本地化操作。

        通过 NetworkDriver 执行容器网络环境的配置。

        通过 ExecDriver 执行容器内部运行的执行工作。


    Docker Daemon 和 Docker Client 的启动都是通过可执行文件 Docker 来完成的,因此两者的启动流程非常相似。

    

    Docker 可执行文件运行时,运行代码通过不同的命令行参数,区分两者,并运行两者各自相应的部分。

    启动 Docker Daemon 时,一般可以使用以下命令来完成:

docker --daemon = truedocker –d
docker –d = true


    再由 Docker 的 main() 函数来解析以上命令的相应 Flag 参数,并最终完成 Docker Daemon 的启动。


    Docker Daemon 的启动流程:

        e69.jpg



    默认配置下,Docker Daemon 只能响应来自本地 Host 的客户端请求。如果要允许远程客户端请求,需要在配置文件中打开 TCP 监听。

    1、编辑配置文件/etc/systemd/system/multi-user.target.wants/docker.service,在环境变量 ExecStart 后面添加 -H tcp://0.0.0.0,允许来自任意 IP 的客户端连接。

$ vim /etc/systemd/system/multi-user.target.wants/docker.service 
.....
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0
.....


    2、重启Docker Daemon

systemctl daemon-reload
systemctl restart docker


    3、通过以下命令实现与远程Docker服务器通信

    -H:指定Docker服务器主机

    info :查看 Docker 服务器的信息

$ docker -H 192.168.184.36 info




    Docker Image

    Docker 镜像可看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

    镜像不包含任何动态数据,其内容在构建之后也不会被改变。可将 Docker 镜像看成只读模板,通过它可以创建 Docker 容器。


    镜像有多种生成方法:

        从无到有开始创建镜像

        下载并使用别人创建好的现成的镜像

        在现有镜像上创建新的镜像


    可以将镜像的内容和创建步骤描述在一个文本文件中,这个文件被称作 Dockerfile ,执行 docker build <docker-file> . 命令构建出 Docker 镜像。



    Docker Registry

    Docker Registry 是存储 Docker Image 的仓库,在 Docker 生态环境中的位置如下图所示:

    09.jpg

    运行 docker push、docker pull、docker search 时,实际上是通过 Docker Daemon 与 Docker Registry 通信。



    Docker Container

    Docker 容器就是 Docker 镜像的运行实例,是真正运行项目程序、消耗系统资源、提供服务的地方。

    Docker Container 提供了系统硬件环境,使用 Docker Images 制作好的系统盘,再加上编写好的项目代码,Run 一下就可以提供服务。


    Docker 组件协作运行容器可以分为以下几个过程:

        1、Docker 客户端执行 docker run 命令;

        2、Docker Daemon 发现本地没有我们需要的镜像;

        3、Daemon 从 Docker Hub 下载镜像;

        4、下载完成后,镜像被保存到本地;

        5、Docker Daemon 启动容器。

    如果本地已下载镜像,则过程只有 1和5。



六、Docker底层技术

    LXC:Linux容器技术,共享内核,容器共享宿主机资源,使用namespace和cgroups对资源限制和隔离。

    Cgroups(Control groups):将所有进程放到一个组里面统一管理的机制。主要提供了资源限制、优先级分配、资源统计、进程控制的作用。   

     Namespace:命名空间,Linux内核提供的一种限制单进程或多进程的资源隔离机制,一个进程可以属于多个命名空间。Linux内核提供六种Namespace:UTS、IPC、PID、Network、Mount和User。

    UFS(UnionFS):联合文件系统,支持将不同位置的目录挂载到统一虚拟文件系统,形参一种分层的模型,成员目录称为虚拟文件系统的一个分支(Branch)。

    

    UFS Namespace:允许每个container拥有独立的hostname和 domain name, 使其在网络上可以被视作一个独立的节点而非Host上的一个进程。

    IPC Namespace:容器中进程交互还是采用linux常见的进程间交互方法 (interprocess communication - IPC),包括常见的信号量、消息队列和共享内。

    PID Namespace:用来隔离不同用户的进程。

    Network Namespace:隔离容器的网路。

    Mount Namespace:类似chroot,将进程放在特定目录执行。允许不同namespace的 进程看到的文件结构不同。

    User Namespace:使得每个container(容器)可以有不同的user和group id。



七、Docker存储驱动

    http://dockone.io/article/1765


点赞
说说你的看法

所有评论: (0)

# 加入组织

1、用手机QQ扫左侧二维码

2、搜Q群:1058582137

3、点击 宁时修博客交流群