Docker基础知识详解

1. docker 是什么

Docker是一款以容器虚拟化技术为基础的软件。

什么是虚拟化技术

虚拟化技术是一种将计算机物理资源进行抽象、转换为虚拟的计算机资源提供给程序使用的技术。常见的计算机资源包括CPU、内存、硬盘存储、网卡等。通过虚拟化技术来管理计算机资源,不但能对计算机资源的控制变得更加灵活,也大幅提高了计算机资源的使用率。

虚拟化的分类

在实现虚拟化的方式上主要有硬件虚拟化和软件虚拟化两大类。硬件虚拟化指的是物理硬件本身就提供虚拟化的支持。比如,某些CPU 能够自身模拟裂变,让程序或者操作系统认为存在多个 CPU,进而能够同时运行多个程序或者操作系统。软件虚拟化则是通过软件的方式来实现虚拟化中关键的指令转换部分,主要方式是通过一层夹杂在应用程序和硬件平台上的虚拟化实现软件来进行指令的转换。

在实际应用场景中,虚拟化还能进行更细化的分类,比如

  • 平台虚拟化:在操作系统和硬件平台间搭建虚拟化设施,使得整个操作系统都运行在虚拟后的环境中。
  • 应用程序虚拟化:在操作系统和应用程序间实现虚拟化,只让应用程序运行在虚拟化环境中。
  • 内存虚拟化:将不相邻的内存区,甚至硬盘空间虚拟成统一连续的内存地址。
  • 桌面虚拟化:让本地桌面程序利用远程计算机资源运行,达到控制远程计算机的目的。

虚拟机

虚拟机,通常是通过一个虚拟机监视器 ( Virtual Machine Monitor ) 的设施来隔离操作系统与硬件或者应用程序和操作系统,以此达到虚拟化的目的。这个夹在其中的虚拟机监视器,常常被成为 Hypervisor

 虚拟机技术得益于 Hypervisor 的加持,使得应用程序或者操作系统可以在无任何修改的情况下运行在另一平台上,但其有一个致命的缺陷,就是所有的指令都必须经过虚拟机监视器的处理,这也就意味着虚拟机的性能是低下的。所以虚拟机不仅仅是Hypervisor加持,还有硬件辅助虚拟化的应用。

容器技术

所谓容器技术,指的是操作系统自身支持一些接口,能够让应用程序间可以互不干扰的独立运行,并且能够对其在运行中所使用的资源进行干预。由于应用程序的运行被隔离在了一个独立的运行环境之中,就好似一个容器,包裹住了应用程序,这也是容器技术名字的由来。

虚拟机 VS 容器

 图片来自掘金:掘金课程

容器技术没有了虚拟操作系统和虚拟机监视器这两个层次,大幅减少了应用程序运行带来的额外消。而且容器中的应用程序其实完全运行在了宿主操作系统中,与其他真实运行在其中的应用程序在指令运行层面是完全没有任何区别的。

2. docker技术实现

Docker 项目是一个由 Go 语言实现的容器引擎,它最初由 dotCloud 这家做云服务的公司在 2013 年开源。Docker的实现,主要归结于三大技术:命名空间 ( Namespaces ) 、控制组 ( Control Groups ) 和联合文件系统 ( Union File System )

  • Namespaces:命名空间是 Linux 核心在 2.4 版本后逐渐引入的一项用于运行隔离的模块。Linux 内核的命名空间,就是能够将计算机资源进行切割划分,形成各自独立的空间。就实现而言,Linux Namespaces 可以分为很多具体的子系统,如 User Namespace、Net Namespace、PID Namespace、Mount Namespace 等。通过 PID Namespace,可以造就一个独立的进程运行空间,在其中进程的编号又会从 1 开始。在这个空间中运行的进程,完全感知不到外界系统中的其他进程或是其他进程命名空间中运行的进程。
  • CGroups:资源控制组是 Linux 内核在 2.6 版本后逐渐引入的一项对计算机资源控制的模块。与以隔离进程、网络、文件系统等虚拟资源为目的 Namespace 不同,CGroups 主要做的是硬件资源的隔离。CGroups 除了资源的隔离,还有资源分配这个关键性的作用。通过 CGroups,我们可以指定任意一个隔离环境对任意资源的占用值或占用率。
  • 联合文件系统:是一种能够同时挂载不同实际文件或文件夹到同一目录,形成一种联合文件结构的文件系统。Docker 将其引入到容器实现中,用它解决虚拟环境对文件系统占用过量,实现虚拟环境快速启停等问题。

2.1 docker的核心概念

  • Docker镜像(Image) :类似于虚拟机镜像,可以理解为一个面向Docker引擎的只读模板,包含了文件系统。 镜像(Image)是创建Docker容器的基础。通过版本管理和增量的文件系统,Docker提供了一条十分简单的机制来创建和更新现有的镜像。 
  • Docker容器(Container) : container类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。Container是从镜像创建的应用运行实例,可以将其启动、开始、停止、删除,而容器Container之间都是相互隔离、互不可见的。 镜像自身是只读的。容器从镜像启动的时候,Docker会在镜像的最上层创建一个可写层,镜像本身将保持不变。
  • Docker仓库(Repository) :Repository类似于代码仓库,是Docker集中存放镜像文件的场所。 每个仓库集中存放某一类镜像,往往包括多个镜像文件,通过不同的标签(tag)来进行区分。 根据存储的镜像公开与否,Docker仓库可以分为公开仓库和私有仓库两种形式。

2.2.1 docker镜像

Docker 镜像其实是由基于 UnionFS 文件系统的一组镜像层依次挂载而得,而每个镜像层包含的其实是对上一镜像层的修改,这些修改其实是发生在容器运行的过程中的。所以,镜像是对容器运行环境进行持久化存储的结果。对于每一个记录文件系统修改的镜像层来说,Docker 都会根据它们的信息生成了一个全球唯一的 64位Hash 码。

镜像的命名可以分成三个部分:usernamerepository 和 tag。可以没有username。

镜像的使用:

  • 查看镜像: docker images 。在 docker images 命令的结果中,可以看到镜像的 ID ( IMAGE ID)、构建时间 ( CREATED )、占用空间 ( SIZE ) 等数据。
  • 查找镜像:docker search 镜像名字;
  • 下载镜像:docker pull [options]   镜像名称[:tags]。
  • 推送镜像:docker push 镜像:tags
  • 运行镜像: docker run -i -t 镜像名字 在启动的容器里执行的命令。-t:在新容器内指定一个伪终端或终端。-i:允许你对容器内的标准输入 (STDIN) 进行交互。使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。

镜像和层:
Docker 镜像由一系列层组成。每个层代表镜像的 Dockerfile 中的一条指令。除了最后一个层之外,每个层都是只读了。当你创建一个新的容器时,你在底层上添加一个新的可写层。这个层通常被称为“容器层”。对正在运行的容器所做的所有更改(如写入新文件,修改现有文件和删除文件)都会写入此可写容器层.

2.2.2 容器

大体上看,容器的生命周期分为:Created、Running、Paused、Stopped、Deleted。在 Docker 的设计中,容器的生命周期其实与容器中 PID 为 1 这个进程有着密切的关系。当容器中的主进程主动关闭时 ( 正常结束或出错停止 ),也会让容器随之停止。

由于每个容器都有自己的可写的容器层,并且所有更改都存储在此容器层中,因此多个容器可以共享对相同基础镜像的访问权限,并且拥有自己的数据状态。(图来自:Docker 在容器中存储数据 - 关于存储驱动程序_kikajack的博客-CSDN博客)

容器写时复制机制Copy on Write
Docker 在通过镜像运行容器时,并不是马上就把镜像里的所有内容拷贝到容器所运行的沙盒文件系统中,而是利用 UnionFS 将镜像以只读的方式挂载到沙盒文件系统中。只有在容器中发生对文件的修改时,修改才会体现到沙盒环境上。所以,容器在创建和启动的过程中,不需要进行任何的文件系统复制操作,也不需要为容器单独开辟大量的硬盘空间。可以说,Docker 容器能够实现秒级启动速度,写时复制机制在其中发挥了举足轻重的作用。

2.2.3 docker私有仓库安装

有非常多的实例,这里就不再赘述。

3. 构建docker镜像

构建Docker镜像有以下两种方法:

  • 使用docker commit命令。docker commit 构建镜像可以想象为是在往版本控制系统里提交变更。(不推荐使用)
  • 使用docker build命令和 Dockerfile 文件。

3.1 创建DockerFile

Dockerfile由一系列指令和参数组成,基于DSL语法。每条指令都必须为大写字母,切后面要跟随一个参数。Dockerfile中的指令会按照顺序从上到下执行,每条指令都会创建一个新的镜像层并对镜像进行提交。Docker大体上按照如下流程执行Dockerfile中的指令:

  • Docker从基础镜像运行一个容器。
  • 执行第一条指令,对容器进行修改。
  • 执行类似docker commit的操作,提交一个新的镜像层。
  • Docker再基于刚提交的镜像运行一个新的容器。
  • 执行Dockerfile中的下一条命令,直到所有指令都执行完毕。

DockerFile的常见写法:

  • FROM:每个Dockerfile的第一条指令都应该是FROM。FROM指令指定一个已经存在的镜像,后续指令都是将基于该镜像进行,这个镜像被称为基础镜像(base iamge)
  • MAINTAINER:这条指令会告诉Docker该镜像的作者是谁,以及作者的邮箱地址。这有助于表示镜像的所有者和联系方式。
  • RUN:RUN指令会在当前镜像中运行指定的命令。每条RUN指令都会创建一个新的镜像层,如果该指令执行成功,就会将此镜像层提交,之后继续执行Dockerfile中的下一个指令。
  • EXPOSE:EXPOSE指令是告诉Docker该容器内的应用程序将会使用容器的指定端口。出于安全的原因,Docker并不会自动打开该端口,而是需要你在使用docker run运行容器时来指定需要打开哪些端口。
FROM    centos:6.7
MAINTAINER      Cruise "xxxx@163.com"
RUN     /bin/echo 'root:123456' |chpasswd
RUN     useradd five3
RUN     /bin/echo 'xxxx:123456' |chpasswd
RUN     /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE  22
EXPOSE  80
CMD     /usr/sbin/sshd -D

最后执行docker build -t xxxx/centos:6.7 /path/to/dockerfile 。 -t :指定要创建的目标镜像名,注意名称只能是小写字母

4. docker持久化

容器删除后,任何写到容器但没有保存到数据卷的数据都会和容器一同删除。为了不让数据随着container的消失而消失,保证数据的安全性,这就有了Volume的存在。例如:数据库容器,数据表的表会产生一些数据。

4.1 数据卷

数据卷是经过特殊设计的目录,可以绕过联合文件系统,为一个或多个容器提供服务。其目的在于数据的持久化,完全独立于与容器的生命周期。数据卷的架构理解:

  1. 独立于docker的存在。存在与宿主机中。与docker容器的生存在周期是分离的。
  2. 本质上使存在于宿主机的文件系统中
  3. docker数据卷可以是目录,也可以是文件。
  4. docker容器可以利用数据卷的技术可以与宿主机进行数据共享。
  5. 同一个目录或者文件,可以支持多个容器的访问。实现了容器间的数据进行交换。

特点:

  1. 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了包含了数据,这些数据会拷贝到新初始化的数据卷中。
  2. 数据卷可以在容器之间共享和重用;
  3. 可以对数据卷里的内容直接进行修改,数据卷的变化不会影响镜像的更新
  4. 数据卷会一直存在,即使挂载数据卷的容器已经被删除

4.2 数据卷容器

一个命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器,就叫做数据卷容器。docker常通过volume driver 来实现数据持久化和文件共享功能,具体有两种存在方式, 分别是:

1. bind mount 方式
将host的目录或文件直接mount到容器中, host的目录或文件既可以容器运行之前就已存在的, 也可以是在容器运行之前不存在的。如果在docker run 命令中采用了 -v /host/dir_or_file:/container/dir_or_file的形式, 就是bind mount方式, 即指定了host的挂载点的绝对路径。

2. volume 方式

由 Docker 管理, 该volume最终存储到host的 /var/lib/docker/volumes 下。 volume 方式还分为 named volume 和 Anonymous volume。

  • named volume 有两种创建方法,:
    • 1) docker run 命令中采用了 -v one_volume_name:/container/dir_or_file , 这里的one_volume_name不是host中的绝对路径, 而是一个名称. 
    • 2) 通过 docker volume create 创建的, 该命令支持更多的选项, 推荐使用。
  • 匿名volume方式 是通过 docker run 命令中传入了 -v /container/dir 类型的参数。

主要有两种数据存储形式, 一种是storage driver(也叫做 Graph driver), 另一种是 volume driver. stroage driver主要是存储那些无状态的数据, 写入密集型的场景应该使用 volume driver。volumn driver更常见,

#创建一个名 为 dbstore 的数据容器, 设置一个匿名的/dbdata volume. 
docker create -v /dbdata --name dbstore busybox /bin/sh 
 
#创建一个名为 web3 的应用容器, 将 dbstore 数据容器的volume 挂载过来. 
docker run -d --name web3 --volumes-from dbstore busybox /bin/sh 
 
#备份数据容器 dbstore 的/dbdata目录到容器到host的host_backup目录下, 最终在host上的文件名为 /host_backup/backup.tar
docker run --rm --volumes-from dbstore  -v /host_backup:/backup busybox tar -cvf /backup/backup.tar /dbdata
 
#思路: 先新建一个数据卷容器,再建一个新的容器并挂载该数据卷容器,然后再把tar包解包。
 
#恢复数据容器dbstore 的/dbdata目录, 数据源为host上的文件 /host_backup/backup.tar
docker run --rm --volumes-from dbstore -v /host_backup:/backup busybox /bin/sh -c "cd /dbdata && tar -xvf /backup/backup.tar --strip 1"

// 挂载多个目录
docker run --name data -v /opt/data1:/var/www/data1 -v /opt/data2:/var/www/data2:ro -t -i docker.io/ubuntu /bin/bash

参考链接:https://blog.csdn.net/chenwiehuang/article/details/84187450

Docker容器数据卷-Volume小结 - 散尽浮华 - 博客园https://blog.csdn.net/hhq12/article/details/81660675 
 docker 系列 - 容器数据持久化和数据共享 - harrychinese - 博客园

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值