热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Docker镜像、容器剖析

我们通常所说的docker是什么?在这里英文本意为“搬运工”这里指的的docker搬运点的是集装箱,集装箱装的是够任意类型的APP,开发者通过Docker可以将app变成一种标准化,可移植的、自管

我们通常所说的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  底层技术]

docker底层的 2 个核心技术分别是 Namespaces 和 Control groups

Namespaces用来隔离各个容器

1)pid namespace

不同用户的进程就是通过pid namespace 隔离开的,且不同  namespace  中可以有相同pid。所有的LXC进程在docker中的父进程为docker进程,每个lxc进程具有不同的 namespace 。

 

2) net namespace

有了pid namespace,  每个 namespace 中的pid能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net namespace 实现的,每个 net namespace 有独立的  network devices, IP addresses, IP routing tables, /proc/net  目录。这样每个 container 的网络就能隔离开来。docker默认采用veth的方式将 container 中的虚拟网卡同 host 上的一个docker bridge: docker0 连接在一起。

 

3) ipc namespace

container 中进程交互还是采用linux常见的进程间交互方法 (interprocess communication - IPC),包括常见的信号量、消息队列和共享内存。container  的进程间交互实际上还是host 上具有相同pid namespace 中的进程间交互。

 

4) mnt namespace

类似chroot,将一个进程放到一个特定的目录执行。mnt namespace 允许不同 namespace 的进程看到的文件结构不同,这样每个  namespace  中的进程所看到的文件目录就被隔离开了。在container里头,看到的文件系统,就是一个完整的linux系统,有/etc、/lib 等,通过chroot实现。

 

5) uts namespace

UTS("UNIX Time-sharing System") namespace 允许每个 container 拥有独立的 hostname 和 domain name,  使其在网络上可以被视作一个独立的节点而非 Host 上的一个进程。

 

6) user namespace

每个 container 可以有不同的  user  和  group id,  也就是说可以在 container 内部用 container 内部的用户执行程序而非 Host 上的用户。

 

有了以上 6 种 namespace 从进程、网络、IPC、文件系统、UTS和用户角度的隔离,一个 container 就可以对外展现出一个独立计算机的能力,并且不同 container 从 OS 层面实现了隔离。然而不同 namespace 之间资源还是相互竞争的,仍然需要类似ulimit来管理每个 container 所能使用的资源 - -cgroup。

cgroups(Control groups)实现了对资源的配额和度量。

 【创建自己的镜像】

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

1.1:先下载一个容器

docker pull training/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

 


推荐阅读
  • 本文将详细介绍如何在ThinkPHP6框架中实现多数据库的部署,包括读写分离的策略,以及如何通过负载均衡和MySQL同步技术优化数据库性能。 ... [详细]
  • 全面解析运维监控:白盒与黑盒监控及四大黄金指标
    本文深入探讨了白盒和黑盒监控的概念,以及它们在系统监控中的应用。通过详细分析基础监控和业务监控的不同采集方法,结合四个黄金指标的解读,帮助读者更好地理解和实施有效的监控策略。 ... [详细]
  • 解决TensorFlow CPU版本安装中的依赖问题
    本文记录了在安装CPU版本的TensorFlow过程中遇到的依赖问题及解决方案,特别是numpy版本不匹配和动态链接库(DLL)错误。通过详细的步骤说明和专业建议,帮助读者顺利安装并使用TensorFlow。 ... [详细]
  • 深入解析Serverless架构模式
    本文将详细介绍Serverless架构模式的核心概念、工作原理及其优势。通过对比传统架构,探讨Serverless如何简化应用开发与运维流程,并介绍当前主流的Serverless平台。 ... [详细]
  • 本文将详细介绍多个流行的 Android 视频处理开源框架,包括 ijkplayer、FFmpeg、Vitamio、ExoPlayer 等。每个框架都有其独特的优势和应用场景,帮助开发者更高效地进行视频处理和播放。 ... [详细]
  • 为了解决不同服务器间共享图片的需求,我们最初考虑建立一个FTP图片服务器。然而,考虑到项目是一个简单的CMS系统,为了简化流程,团队决定探索七牛云存储的解决方案。本文将详细介绍使用七牛云存储的过程和心得。 ... [详细]
  • 本文详细介绍了如何在云服务器上配置Nginx、Tomcat、JDK和MySQL。涵盖从下载、安装到配置的完整步骤,帮助读者快速搭建Java Web开发环境。 ... [详细]
  • 优化Flask应用的并发处理:解决Mysql连接过多问题
    本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
  • 本文详细介绍了如何正确配置Java环境变量PATH,以确保JDK安装完成后能够正常运行。文章不仅涵盖了基本的环境变量设置步骤,还提供了针对不同操作系统下的具体操作指南。 ... [详细]
  • 微信小程序中实现位置获取的全面指南
    本文详细介绍了如何在微信小程序中实现地理位置的获取,包括通过微信官方API和腾讯地图API两种方式。文中不仅涵盖了必要的准备工作,如申请开发者密钥、下载并配置SDK等,还提供了处理用户授权及位置信息获取的具体代码示例。 ... [详细]
  • 本文详细介绍了 Kubernetes 集群管理工具 kubectl 的基本使用方法,涵盖了一系列常用的命令及其应用场景,旨在帮助初学者快速掌握 kubectl 的基本操作。 ... [详细]
  • 本文详细介绍如何使用CSS自定义HTML5视频播放器的样式,涵盖常见属性及跨浏览器兼容性问题。发布时间:2020-09-14 14:46:29;来源:亿速云;阅读量:58;作者:小新。 ... [详细]
  • 本文详细介绍了如何在预装Ubuntu系统的笔记本电脑上安装Windows 7。针对没有光驱的情况,提供了通过USB安装的具体方法,并解决了分区、驱动器无法识别等问题。 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
  • 三菱PLC SLMP协议报文详解
    本文详细解析了三菱PLC中使用的SLMP协议报文结构,包括其工作原理、通信流程及报文格式,旨在帮助工程师和技术人员更好地理解和运用这一协议。 ... [详细]
author-avatar
吕小布
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有