Docker镜像、容器剖析

我们通常所说的docker是什么?

在这里英文本意为“搬运工”这里指的的docker搬运点的是集装箱,集装箱装的是够任意类型的APP,开发者通过Docker可以将app变成一种标准化,可移植的、自管理的组件、可以在任意主流的系统开发,调试和运行

  简单的来说,docker是一种用了新颖的方式实现的轻量级的虚拟化,类似于VM,但是在原理和应用上和VM还是有很大的区别,其专业的名称是应用容器;

所谓应用容器,就比如将Nginx,Mysql等软件程序将其封装成一组特定的虚拟机一样,如果我们想用Nginx这些应用的话,我们直接运行这个容器就好了,这就相当于运行起来的虚拟机一样,只要能运行,这些配置都省下来了,如果说系统层面的宿主机出现了异常需要迁移,那么我们将这个容器转移平台就可以的

   Docker基于Go语言开发的,代码托管在Github上,docker容器可以封装任何有效负载,计划可以在任何服务器之间进行一致性运行,也就是说,开发者构建的应用,只需要一次构建即可多平台运行,运营人员只需要配置服务,即可运行所有应用,

    若是利用容器的话,那么开发直接在容器里开发,测试的时候整个同期给测试,测好了把测试后容器再上线就好了,通过容器,整个开发,测试和生产环境保持高度一致;

 此外容器也有和VM一样具有一定的隔离性,各个容器之间的数据和内存之间相互隔离,可以保证一定的安全性

      Hyper-V、KVM和XEN等虚拟机管理程序都是“”基于虚拟化硬件仿真机制”,这就意味着,它们对系统硬件要求很高,然而,容器确实使用共享的操纵系统,它们在使用系统资源方面比虚拟机管理程序要高效很多,容器不是对硬件要求进行的虚拟化的处理,而是驻留在一个linux实例上,Docker可以解决虚拟机能够解决的问题,同时也能解决虚拟机由于资源要求过高而无法解决的问题

为什么使用Docke?或者是docker有哪方面的优势

1)快速的交付应用程序

开发者使用一个标准image来构建开发容器,开发完成之后,系统管理员就可以使用这个容器来部署代码

docker可以快速的创建容器,快速的迭代应用程序,并让整个过程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的

docker容器轻量级,启动很快,启动的时候是次秒级的,节约开发,测试,部署时间

2)更容易部署和扩展

docker容器可以在几乎所有环境中运行,物理机,虚拟机,公有云,私有云,服务器等等

docker容器兼容很多平台,这样就可以把一个应用程序从一个平台上迁移到到另一个

3)效率高

Docker容器不需要hypervisor,他是内核级虚拟化

4)快速的部署也以为这更简单的管理

通常是需要小小的改变就可以替代以往巨型和大量更新工作

【Docker常用的案列】

自动打包和部署应用

创建轻量,私有的Paas环境

自动化测试和持续集成/部署

部署并扩展WEB应用/数据库和后端服务器

【VM的选用】

docker容器相对于VM还是有很多优点的,

1)启动速度快,容器通常在一秒内可以启动,而VM要很久

2)资源利用率小,一台普通服务器可以跑上个容器

3)性能开销小,VM需要额外的CPU和内存来完成OS的功能,这一部分占据了额外的资源

下图所示:对比了docker和传统虚拟化(KVM,XEN等)方式的不同之处,Docker容器是在操作系统层面上实现了虚拟化,直接复用本地主机操作系统,而传统方式则是在硬件基础上,虚拟出自己的系统,再在系统上部署相关的APP应用

传统虚拟化方案:Nginx(图一)

Docker虚拟化解决方案:Nginx镜像-nginx容器-对外访问

Docker虚拟化三个概念解析:镜像,容器,仓库

镜像:Docker的镜像其实就是模板,跟我们常见的ISO镜像类似,是一个样板

容器:使用镜像常见的应用或者系统,称之为一个容器

仓库:仓库是存放镜像的地方,分为公开仓库(Public)和私有仓库(Private)两种形式

Docker最早为LXC+AUFS组合,Docker0.9.0版本开始引入libcontainer,可以视作LXC的替代品,其中LXC负责资源管理,AUFS负责镜像管理;而LXC包括Cgroup,namespace,chroot等组件,并通过cgroup进行资源管理

 从资产管理来看,Docker,LXC,Cgroup三者的关系是:cgroup在最底层落实资源管理,LXC在cgroup上封装了一层,Docker又在LXC封装了一层

    Cgroup是linux内核提供的一种可以限制,记录,隔离进程组所使用的物理资源(如CPU,Memory,IO等)的机制,Cgroups也是LXC为实现虚拟化所使用的资源管理手段,可以说没有Cgroups也就没有LXC,也就没有Docker

   Cgroup最初的目的地为资源管理提供一个统一的框架,即整合现有的Cgroup等子系统,也为未来开发新的子系统提供接口,现在的Cgroup使用与多种应用场景,从单个进程的资源控制,到实现操作系统层次的虚拟化

  LXC容器可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性,容器有效的将单个系统管理的资源划分到独立的组中,以便更好的在独立的组之间平衡有冲突的资源使用需求

【对比传统的虚拟机总结】

【Docker的体系结构】

docker使用C/S架构,docker daemon作为server端接受clinet的请求,并处理(创建,运行,分发容器)他们可以运行在一个机器上,也通过socket或者去RESTful API通信

Docker daemon一般在宿主机后台运行,docker clinet以系统命令形式存在,用户用docker命令与docker daemon交互;

docker守护进程(docker daemon)

如图上所示,docker守护进程运行在一台主机上,用户并不直接和守护进行交互,而通过docker客户端间接和其通信

Docker客户端(Docker client)

Docker客户端实际上是docker的二进制程序,是用户与docker交互方式,它接受用户指令并且与背后的docker守护进程通信;

Docker 内部:

要理解 Docker 内部构建,需要理解以下三种部件:

Docker 镜像 - Docker images 

docker镜像是docker容器运行时的只读模板,镜像可以用来创建docker容器。每个镜像由一系列层的(layers)组成,Docker使用的UFS(联合文件系统)来讲这些层联合到单独的镜像中,

UFS允许独立文件系统中的文件和文件夹被透明覆盖,形成一个单独连贯的文件系统,正因为有了这些镜像层的存在,docker是如此的轻量,当你改变一个docker镜像,比如说升级到某个程序最新版本,这样一个新的层会被创建,不需要替换或者是说重新创建,只需要升级,层使得分发docker镜像变得简单和快速;

每个docker都有很多层次构成,docker使用  union file systems  将这些不同的层结合到一个image 中去。

例如:centos镜像中安装nginx,就成了nginx镜像”,其实在此时Docker镜像的层级概念就体现出来了。底层一个centos操作系统镜像,上面叠加一个ngnx层,就完成了一个nginx镜像的构建。层级概念就不难理解,此时我们一般centos操作系统镜像称为nginx镜像层的父镜像。

Docker 仓库 - Docker registeries

docker仓库用来保存镜像,可以理解为代码控制中的代码仓库,同样的,docker仓库也有共公有和私有的概念,公有Docker仓库名字是docker hub,docker hub提供了庞大的镜像集合供使用,这些镜像可以是自己创建的,或者在比人的镜像基础上创建

仓库是集中存放镜像文件的场所,有时候会把仓库 和仓库注册服务器(Regitry)混为一谈,

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

最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括 Docker Pool等,可以提供大陆用户更稳定快速的访问。

当然,用户也可以在本地网络内创建一个私有仓库。

当用户创建了自己的镜像之后就可以使用push命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上pull下来就可以了。

*注:Docker 仓库的概念跟Git类似,注册服务器可以理解为 GitHub 这样的托管服务。

Docker 容器 - Docker containers

Docker 利用容器来运行应用,一个Docker容器包含了所有的某个应用运行所需要的环境。每一个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运行、开始、停止、移动和删除。每一个 Docker 容器都是独立和安全的应用平台。

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

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

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

 【总结】到此,我们来总结一下Docker的优势和缺点

优势:1)快速的部署:短时间类可以部署成百上千个应用,快速的交付到线上;

           2)高效的虚拟化:传统的虚拟化是基于硬件层面上实现的虚拟化,而我们的docker是在系统层面上实现的,不需要基于Hyprevisor的支持,想比较虚拟机大幅度提高性能和效率

          3)节省开支:更好的提高服务器的利用率;

          4)简化配置:将运行的环境打包至容器。使用时直接启动即可

          5)快速的迁移扩展:我们可以快速将容器进行打包迁移到需要的平台上应用,拥有良好的兼容性;

ps:这里Hyprevisor可以理解基础物理服务器和操作系统中间的软件层,可以协调硬件资源的访问

缺点:1)隔离性:虽然docker提供了Namespace隔离系统资源,但是应用之间的隔离还不如虚拟机

           2)安全性:目前docker server无法判断容器是由哪个用户启动的,比如说,删除的时候不会做用户权限审核;

           3)稳定性以及功能兼容性:因为docker版本还在不断的更新迭代中,很多功能都依赖于高版本的linux系统内核,因此兼容性还是存在一些问题

进入正在运行的容器

进入正在使用的容器有三种方式,分别为:

1)docker attach 【容器名称】:attach类似于VNC,操作会在各个容器界面显示。所以进入容器的操作都是同步显示,但是呢,e​​xit退出容器,,容器也随停止掉,故不推荐使用

2)docker exec -it 【容器名称/id】:执行单次命令进入容器,不是很推荐此方式,虽然exit退出后容器不会停止

3)nsenter -t 【容器pid】-m -u -i -n -p:通过这种方式进入容器,前提是必须要知道容器的PID号,才能执行,可以通过docker inspect -f {{.State .Pid}} 【容器名称】来获取容器的PID号

拓展一下哈,我们可以写成一个脚本工具,通过这个脚本来进入容器

 

shell# vim docker- in

# !/bin/ bash

docker - in (){

NAME =$ 1

PIDNAME =$(docker inspect -f " {{.State.Pid}} " ${NAME})

nsenter -t ${PIDNAME} -m -u -i -n - p

}
docker - in $ 1

# chmod +x docker- in

# docker-in centos7
[root@f3d64292da7f /]# ls
bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

 

 

 

 

 

【创建自己的镜像】

一:使用docker commit 来扩展一个image

1.1:先下载一个容器

docker pull tr​​aining/sinatra

1.2用容器启动这个镜像

docker run -t -i training/sinatra /bin/bash 

1.3:接下来给使用中的容器,添加自己需要的工具,组装自己的运行环境

1.4:结束后,我们使用exit来退出,现在我们的容器已经改变了,我们使用docker commint命令来提交相应的副本

docker commit -m “Added json gem” -a “xiaoyu”    0b2616b0e5a8 ouruser/sinatra:v2 

其中, -m 来指定提交的说明信息,跟我们使用的版本控制工具一样; -a 可以指定更新的用户信息;之后是用来创建镜像的容器的ID;最后指定目标镜像的仓库名和tag 信息。创建成功后会返回这个镜像的ID信息。

 二:从dockerfile来创建image

使用docker commit 来扩展一个image 比较简单,但它不容易在一个团队中分享它。我们使用docker build 来创建一个新的image 。为此,我们需要创建一个dockerfile,包含一些如何创建我们的image 的指令。现在,我们来创建一个目录和一个dockerfile

 

Dockerfile基本的语法是

使用#来注释

FROM指令告诉Docker 使用哪个镜像作为基础(docker使用哪个image 源)

MAINTAINER是维护者的信息

RUN开头的指令会在创建中运行,比如安装一个软件包,在这里使用yum来安装了一些软件

编写完成Dockerfile后可以使用docker build 来生成镜像。

 

2.1、创建镜像所在的文件夹和Dockerfile文件 
命令: 
1、mkdir sinatra 
2、cd sinatra 
3、touch Dockerfile 
2.2、在Dockerfile文件中写入指令,没一条指令都会更新镜像的信息例如: 
# This is a comment 
FROM ubuntu:14.04 
MAINTAINER Kate Smith ksmith@example.com 
RUN apt-get update && apt-get install -y ruby ruby-dev 
RUN gem install sinatra 
格式说明: 
每行命令都是以 INSTRUCTION statement 形式,就是命令+ 清单的模式。命令要大写,“#”是注解。 
FROM 命令是告诉docker 我们的镜像什么。 
MAINTAINER 是描述 镜像的创建人。 
RUN 命令是在镜像内部执行。就是说他后面的命令应该是针对镜像可以运行的命令。 
2.3、创建镜像 
命令:docker build -t ouruser/sinatra:v2 . 
docker build 是docker创建镜像的命令 
-t 是标识新建的镜像属于 ouruser的 
sinatra是仓库的名称 
:v2 是tag 
“.”是用来指明 我们的使用的Dockerfile文件当前目录的 
2.4、创建完成后,从镜像创建容器 
docker run -t -i ouruser/sinatra:v2 /bin/bash

 

其中  -t  标记来添加 tag,指定新的镜像的用户信息。“.”是Dockerfile所在的路径(当前目录),也可以替换为一个具体的Dockerfile的路径。

可以看到 build 进程在执行操作。它要做的第一件事情就是上传这个Dockerfile内容,因为所有的操作都要依据Dockerfile来进行。然后,Dockfile中的指令被一条一条的执行。每一步都创建了一个新的容器,在容器中执行指令并提交修改(就跟之前介绍过的docker commit  一样)。当所有的指令都执行完毕之后,返回了最终的镜像 id。所有的中间步骤所产生的容器都被删除和清理了。

*注意一个镜像不能超过 127 层

 拓展:

进入容器

在使用 -d 参数时,容器启动后会进入后台。某些时候需要进入容器进行操作,有很多种方法,包括使用docker attach 命令或nsenter命令。

使用docker attach进入容器

 

1.docker attach 允许我们进入后台进程.

2.--sig-proxy=false 不使用容器转发信号,允许我们使用 ctrl -c 来退出,执行dockerps查看在后台运行

但是使用  attach  命令有时候并不方便。当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。

 

也可以执行docker exec进入运行的容器

docker  exec  -it  容器ID/名称 /bin/bash

以上命令返回一个命令界面,exec代表直接在容器中运行命令

 

容器导入和导出

导出容器

docker export [容器 id] > [导出文件]

如果要导出本地某个容器,可以使用docker export 命令。

导入容器

可以使用docker import 从容器快照文件中再导入为镜像

# cat centos6.tar | docker import – centos6:test

#docker images

 

转载于:https://www.cnblogs.com/bixiaoyu/p/8762927.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值