零基础+全方位带你学习探索Docker容器开发实战指南(核心组件说明)
- 核心组件
- 镜像
- 定义概念
- 与容器的关联
- 文件系统
- root文件系统
- bootfs启动文件系统
- 分层存储
- 分层覆盖处理模式
- 镜像的写时复制机制
- 容器
- 容器进程隔离性
- 容器进程隔离性
- 容器存储层
- 数据卷绑定
- 镜像和容器的关系
- Hub库
- 标签Tag
- 仓库名
- Docker Registry(公开)
- 仓库操作简介
- Docker登录操作
- Docker Registry(私有)
核心组件
Docker中有三大核心组件:镜像( Image )、容器( Container )、仓库( Repository )理解了这三个概念,就理解了 Docker 的整个生命周期。
镜像
镜像也是docker的核心组件之一,镜像时容器运行的基础,容器是镜像运行后的形态。
定义概念
总体来说,镜像是一个包含程序运行必要以来环境和代码的只读文件,它采用分层的文件系统,将每一层的改变以读写层的形式增加到原来的只读文件上。
与容器的关联
镜像是一个只读的静态模版,它保存了容器需要的环境和应用的执行代码,可以将镜像看成是容器的代码,当代码运行起来之后,就成了容器,镜像和容器的关系也类似于程序和进程的关系。
文件系统
操作系统可以分为内核和用户空间。对于Linux系统而言,内核启动后,会挂载root文件系统为其提供用户空间支持。
root文件系统
Docker镜像就相当于一个root文件系统,它包含了容器运行所需的程序、库、资源、配置等文件,并且还包含了一些为运行时准备的配置参数(如匿名卷、环境变量、用户等)。它属于一个特殊的文件系统,不包含任何动态数据,并且其内容在构建之后也不会被改变。例如,官方镜像ubuntu:18.04就包含了完整的Ubuntu 18.04最小系统的root文件系统。
bootfs启动文件系统
镜像的最底层是一个启动文件系统(bootfs)镜像,bootfs的上层镜像叫做根镜像,一般来说,根镜像是一个操作系统,例如Ubuntu、CentOS等,用户的镜像必须构建于根镜像之上,在根镜像之上,用户可以构建出各种各样的其他镜像。
分层存储
Docker设计时,采用了Union FS的技术,将其设计为分层存储的架构。实际上,镜像并非像一个ISO那样的打包文件,而是由一组文件系统组成,或者说,由多层文件系统联合组成。
分层覆盖处理模式
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。例如,删除前一层文件的操作,实际上不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。
因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。分层存储的特征还使得镜像的复用、定制变得更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
镜像的写时复制机制
使用docker run命令创建容器镜像时,其实是在原镜像基础上添加了一个可读写的空像。基础镜像内容以只读方式加载,容器访问共享基础镜像资料,用户对文件系统的所有更改都不会影响基础镜像。当然,还有其他方法将更改永久保存到基础镜像中,稍后将详细讨论。
容器
容器是一个运行时环境,是镜像的一个运行状态,它是镜像执行的动态表现。
容器在启动或者创建时,必须指定一个镜像的名称或者id,这时镜像所扮演的角色就是容器的模版,不同的镜像可以构造出不同的容器。
容器进程隔离性
容器可以被创建、启动、停止、删除、暂停等。 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。
容器进程隔离性
容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性。镜像使用的是分层存储,容器也是如此。
容器存储层
每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。
按照Docker最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。
数据卷绑定
容器中的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。 数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。
镜像和容器的关系
镜像( Image )和容器( Container )的关系,就像是面向对象程序设计中的类和实例 一样, 镜像是静态的定义,容器是镜像运行时的实体。
在前面的介绍中,我们已经了解到了容器的使用方法。如果你仔细阅读过前面的内容,你可能已经发现,在启动或创建容器时,必须指定一个镜像的名称或ID。实际上,这个镜像就是容器的模板,不同的镜像可以构建出不同的容器。下面是一个示例命令:
docker run -itd --name nginx-server nginx
命令中的最后一个nginx即表示创建该容器所需要的模版,当然这里还省略了一些信息,这些我们后面的章节会详细介绍。
Hub库
库是一个特定的用户存储镜像的目录,一个用户可以建立多个库来保存自己的镜像。
镜像构建完成后,可以很容易地在当前宿主机上运行。但如果需要在其他服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry就是这样的服务。
标签Tag
Docker Registry中可以包含多个仓库(Repository),每个仓库可以包含多个标签(Tag),每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。
以Ubuntu镜像为例,ubuntu是仓库的名字,其内包含有不同的版本标签,如16.04,18.04。我们可以通过ubuntu:16.04或者ubuntu:18.04来具体指定所需哪个版本的镜像。如果忽略了标签,比如ubuntu,那将视为ubuntu:latest。
仓库名
仓库名经常以两段式路径形式出现,比如jwilder/nginx-proxy,前者往往意味着Docker Registry多用户环境下的用户名,后者则往往是对应的软件名。但这并非绝对,取决于所使用的具体Docker Registry的软件或服务。
Docker Registry(公开)
Docker Registry公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务。
一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。 最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry,并拥有大量的高质量的官方镜像。
除此以外,还有 Red Hat 的 Quay.io;Google 的 Google Container Registry,Kubernetes 的镜像使用 的就是这个服务。 由于某些原因,在国内访问这些服务可能会比较慢。国内的一些云服务商提供了针对 Docker Hub 的镜像服务( Registry Mirror ),这些镜像服务被称为 加速器。常见的有 阿里云加速器、DaoCloud 加速器 等。使 用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从 Docker Hub 下载速度会提高很多。在 安装 Docker 一节中有详细的配置方法。 国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库等。
仓库操作简介
类似于GitHub提供的代码托管服务,Docker Hub也提供了镜像托管服务。Docker Hub是Docker官方的镜像托管中心,让用户可以搜索、创建、分享和管理镜像。用户可以在Docker Hub上找到两类镜像:一类是官方镜像,例如nginx、mysql等;另一类是普通的用户镜像,由用户自己上传。如果用户在访问Docker Hub时速度较慢,可以考虑使用国内的镜像,例如网易提供的镜像。
Docker登录操作
首先,读者打开Docker Hub,注册一个账号,这个比较简单,我就不赘述了。账号注册成功之后,在客户端命令行可以登录我们注册的账号,如下:
Last login: Mon Oct 1 12:20:58 on liboware
[libowareMacBook-Pro:docker alex $ docker login
Login with your Docker Id to push and pull images from Docker Hub.If you don't have a Docker ID,head ove
r to https://hub.docker.com to create one.
Username:liboware
Password:
Login Succeeded
libowareMacBook-Pro:docker alex$
看到Login Succeeded表示登录成功!登录成功之后,接下来就可以使用push命令上传我们自制的镜像了。注意,自制的镜像要能够上传,命名必须满足规范,即namespace/name格式,其中namespace必须是用户名,这里重新构建一个本地镜像并上传到Docker Hub,如下:
看到这个表示镜像已经上传成功了,接下来,别人就可以通过如下命令下载我刚刚上传的镜像:
docker pull wongsung/nginx
pull 下来之后,就可以直接根据该镜像创建容器了。
Docker Registry(私有)
除使用公开服务外,用户还可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 镜 像,可以直接使用做为私有 Registry 服务。在 私有仓库 一节中,会有进一步的搭建私有 Registry 服务的讲 解。
构建开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 docker 命令,不影 响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。在官方的商业化版本 Docker Trusted Registry 中,提供了这些高级功能。 除了官方的 Docker Registry 外,还有第三方软件实现了 Docker Registry API,甚至提供了用户界面以及一些 高级功能。比如,Harbor 和 Sonatype Nexus。