Docker速成:新手变专家!

时间:2024-04-09 12:34:13

Docker介绍

容器历史

1、Chroot Jail 就是常见的chroot命令的用法。它在1979年的时候就出现了,被认为是最早的容器化技术之一。它可以把一个进程的文件系统隔离起来。
2、The FreeBSD Jail (*)实现了操作系统级别的虚拟化,他是操作系统级别虚拟化技术的先驱之一。2000年,伴随FreeBSD4.0版的发布
3、Linux VServer http://linux-vserver.org 使用添加到Linux内核的系统级别的虚拟化功能实现的专用虚拟服务器。允许创建许多独立的虚拟专用服务器(VPS),这些虚拟专用服务器在单个物理服务器上全速同时运行,从而有效地共享硬件资源。VPS提供与传统Linux服务器几乎相同的操作系统环境。可以在这样的VPS上启动所有服务(例如ssh,邮件,Web和数据库服务器),而无需(或者在特殊情况下只需进行很少的修改),就像在任何真实服务器上一样。每个VPS都有自己的用户账户数据库和root密码,并且与其他虚拟机服务器隔离,但它们共享相同的硬件资源。
4、Solaris Containers 也是操作系统级别的虚拟化技术,专为X866和SPARC系统设计。Solaris容器是系统资源控制和通过“区域”提供边界隔离的组合。
5、OpenVZ 是一种Linux中操作系统级别的虚拟化技术。它允许创建多个安全隔离的Linux容器,即VPS。
6、Process Containers 由Google的工程师开发,一般被称为cgroups。
7、LXC 为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求。Linux Container 提供了在单一可控主机节点上支持多个相互隔离的server Container同时执行的机制。Linux COntainer有点像chroot,提供了一个拥有自己进程和网络空间的虚拟环境,但又有别于虚拟机,因为lxc是一种操作系统层次上的资源虚拟化。
8、Warden 在最初阶段,Warden使用LXC作为容器运行时。如今已被CloudFoundy取代。
9、LMCTFY 是Google的容器技术栈的开源版本。Google的工程师一直在与docker的libertainer团队合作,并将libertainerde核心概念进行抽象并移植到此项目中,该项目的进展不明,估计会被libcontainer取代。
10、Docker 是一个可以将应用及其依赖打包到几乎可以在任何服务器上运行的容器工具。
11、RKT 是Rocket的缩写,他是一个专注安全和开放标准的应用程序引擎。
总上所述,docker并不是第一个容器化技术,但它确实最知名的一个。

Docker是什么

Docker(码头工人)是一个开源项目,诞生于2013年初,最初是dotCloud公司(后由于Docker开源后大受欢迎就将公司名改为Docker Inc,总部位于美国加州的旧金山)内部的一个开源的PAAS服务的业余项目。它基于Google公司推出的Go语言实现。项目后来加入了Linux基金会,遵从了Apache2.0协议,项目代码在GitHub上进行维护。
Docker是基于Linux内核实现,Docker是最早采用LXC技术,LXC是Linux原生支持的容器技术,可以提供轻量级的虚拟化,可以说docker就是基于LXC发展起来的,提供LXC的高级封装,标准的配置方法,在LXC的基础上,docekr提供了一系列更强大的功能。而虚拟化技术KVM基于模块实现,后来Docker改为自己研发并开源的runc技术运行容器,彻底抛弃了LXC。
Docker相比虚拟机的交付速度更快,资源消耗更低,Docker采用客户端/服务端架构,使用远程API来管理和创建容器,其可以轻松的创建一个轻量级的、可移植的、自给自足的容器,docker的三大理念是build(构建)、ship(运输)、run(运行),Docker遵从Apache2.0协议,并通过(namespace及cgroup等)来提供容器的资源隔离与安全保障等,所以Docker容器在运行时不需要类似虚拟机(空运行的虚拟机占用物理机6%~8%性能)的额外资源开销,因此可以大幅提高资源利用率,总而言之Docker是一种用了新颖方式实现的轻量级虚拟机,类似于VM,但是在原理和应用上和VM的差别还是很大的,并且Docker的专业叫法是应用容器(Application Container)。
Docker的主要目标:Build,Ship and Run Any App,Anywhere,即通过对应用组件的封装(Packaging)、分发(Distribution)、部署(Deployment)。运行(Runtime)等生命周期的管理,达到应用组件级别的“一次封装,到处运行”。这里的应用组件,既可以是一个Web应用,也可以是一套数据库服务,甚至是一个操作系统。将应用运行在Docker容器上,可以实现跨平台,跨服务器,只需一次配置准备好相关的应用环境,即可实现到处运行,保证研发和生产环境的一致性,解决了应用和运行环境的兼容性问题,从而极大提升了部署效率,减少故障的可能性。
使用Docker容器化封装应用程序的意义

  • 统一基础设施环境-docker环境
    • 硬件的组成配置
    • 操作系统的版本
    • 运行时环境的异构
  • 统一程序打包(装箱)方式-docker镜像
    • Java程序
    • python程序
    • nodejs程序
  • 统一程序部署(运行)方式-docker容器
    • java -jar……—>docker run ……
    • python manage.py……—>docker run ……
    • npm run dev ……—>docker run ……

Docker和虚拟机,物理主机


容器和虚拟机比较

  • 传统虚拟机是虚拟出一个主机硬件,并且运行一个完整的操作系统,然后在这个操作系统上安装和运行软件
  • 容器内的应用直接运行在宿主机的内核之上,容器并没有自己的内核,也不需要虚拟硬件,相当轻量化
  • 每个容器间是互相隔离,每个容器内都有一个属于自己的独立文件系统,独立的进程空间,网络空降,用户空间等,所以在同一个宿主机上的多个容器之间彼此不会互相影响

容器和虚拟机比较

  • 资源利用率更高:开销更小,不需要启动单独的虚拟机OS内核占用硬件资源,可以将服务器性能压榨到极致,虚机一般会有5%~20%的损耗,容器运行基本无损耗,所以生产中一台物理机只能运行数十个虚拟机,但是一般可以运行数百个容器
  • 启动速度更快:可以在数秒内完成启动
  • 占用空间更小:容器一般占用的磁盘空间以MB为单位,而虚拟机以GB
  • 集成性更好:和CI/CD(持续集成/持续部署)相关技术结合性更好,实现打报警箱发布测试可以一键运行,做到自动化并快速的部署管理,实现高效的开发生命周期

使用虚拟机是为了更好的实现服务运行环境隔离,每个虚拟机都有独立的内核,虚拟化可以实现不同操作系统的虚拟机,但是通常一个虚拟机只运行一个服务,很明显资源利用率比较低且造成不必要的性能损耗,我们创建虚拟机的目的是为了运行应用程序,比如Nginx、PHP、Tomcat等web程序,使用虚拟机无疑带来了一些不必要的资源开销,但是容器技术则基于减少中间运行环节带来较大的性能提升。
根据实验,一个运行着Centos的KVM虚机启动后,在不做优化的情况下,虚机自己就占用100~200M内存。此外,用户应用运行在虚机里,它对宿主机操作系统的调用就不可避免地要经过虚拟化软件的拦截和处理,这本身又是一层性能损耗,尤其对计算资源、网络和磁盘I/O的损耗非常大。
比如。一台96G内存的物理服务器,为了运行java程序的虚拟机一般需要分配4核8G的资源,只能运行13台左右的虚机,但是改为在docker容器上运行Java程序,每个容器只需要分配4G内存即可,同样的物理服务器就可以运行25个左右的容器,运行数量相当于提高一倍,可以大幅节省IT支出,通常情况下至少可以节约一半以上的物理设备

Docker的组成

  • Docker主机(Host):一个物理机或虚拟机,用于运行Docker服务进程和容器,也称为宿主机,node节点
  • Docker服务端(Server):Docker守护进程,运行Docker容器
  • Docker客户端(Client):客户端使用docker命令或其他工具调用docker API
  • Docker镜像(Images):镜像可以理解为创建实例使用的模板,本质上就是一些程序文件的集合
  • Docker仓库(Registry):保存镜像的仓库,可以搭建私有仓库harbor
  • Docker容器(Container):容器是从镜像生成对外提供服务的一个或一组服务,其本质就是将镜像中的程序启动后生成进程

Namespace

一个宿主机运行了N个容器,多个容器共用一个OS,必然带来以下问题:

  • 怎样保证每个容器都有不同的文件系统并且互不影响?
  • 一个docker主进程内的各个容器都是其子进程,那么如何实现同一个主进程下不同类型的子进程?各个容器子进程间能相互通信(内存数据)吗?
  • 每个容器怎么解决IP及端口分配的问题?
  • 多个容器的主机名能一样吗?
  • 每个容器都要不要有root用户?怎么解决账户重名问题?

namespace是Linux系统的底层概念,在内核层实现,即有一些不同类型的命名空间被部署在核内,各个docker容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各docker容器运行在宿主机的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件系统,网络空间,进城空间,目前主要通过以下技术实现容器运行空间的相互隔离:

隔离类型 功能 系统调用参数 内核版本
MNT Namespace(mount) 提供磁盘挂载点和文件系统的隔离能力 CLONE_NEWNS 2.4.19
IPC Namespace(Inter Process Communication) 提供进程间通信的隔离能力,包括信号量,消息队列和共享内存 CLONE_NEWIPC 2.6.19
UTS Namespace(UNIX Timesharing System) 提供内核,主机名和域名隔离能力 CLONE_NEWUTS 2.6.19
PID Namespace (Process Identification) 提供进程隔离能力 CLONE_NEWPID 2.6.24
Net Namespace(network) 提供网络隔离能力,包括网络设备,网络栈,端口等 CLONE_NEWNET 2.6.29
User Namespace(user) 提供用户隔离能力,包括用户和组 CLONE_NEWUSER 3.8
MNT Namespace

每个容器都要有独立的根文件系统有独立的用户空间,以实现在容器里面启动服务并且使用容器的运行环境,即一个宿主机是ubuntu的服务器,可以在里面启动一个centos运行环境的容器并且在容器里面启动一个nginx服务,此nginx运行时使用的运行环境就是centos系统目录的运行环境,但是在容器里面是不能访问宿主机的资源,宿主机是使用了chroot技术把容器锁定到一个指定的运行目录里面。

IPC Namespace

一个容器内的进程通信,允许一个容器内的不同进程(内存、缓存等)数据访问,但是不能跨容器直接访问其他容器的数据。

UTS Namespace

UTS namespace (UNIX Timesharing System 包含了运行内核的名称、版本、底层体系结构类型等信息)用于系统标识,其中包含了主机名hostname和域名domainname,它使得一个容器拥有属于自己主机名标识,这个主机名标识独立于宿主机系统和其他上的机器。

PID Namespace

Linux系统中,有一个PID为1的进程(init/systemd)是其他所有进程的父进程,那么在每个容器内也要有一个父进程来管理下属的子进程,那么多个容器的进程通PID namespace进程隔离(比如PID编号重复、容器内的主进程生成与回收子进程等)

NET Namespace

每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP协议栈等,Docker使用network namespace启动一个vethX接口,这样你的容器将拥有它自己的桥接IP地址,通常是docker0,而docker0实质就是Linux的虚拟网桥,网桥是在OSI七层模型的数据链路层的网络设备,通过mac地址对网络进行划分,并且在不同网络直接传递数据。

User Namespace

各个容器内可能会出现重名的用户和用户组名称,或重复的用户UID或者GID,那么怎么隔离各个容器内的用户空间呢?
User Namespace允许在各个宿主机的各个容器空间内创建相同的用户名以及相同的用户UID和GID,只是会把用户的作用范围限制在每个容器内,即A容器和B容器可以有相同的用户名称和ID账户,但是此用户的有效范围仅是当前容器内,不能访问另外一个容器内的文件系统,级相互隔离、互不影响、永不相见。

Control groups

Linux Cgroups的全称是Linux Control Groups,是Linux内核的一个功能,最早由Google的工程师(主要是Paul Menage和Rohit Seth)在2006年发起,最早的名称为进程容器(process containers)。在2007年时,因为在Linux内核中,容器(container)这个名词有许多不同的意义,为避免混乱,被重命名为cgroup,并且被合并到2.6.24版的内核中去。自那以后,又添加了很多功能。
如果不对一个容器做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配限制,比如CPU、内存等。
Cgroups最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等。此外,还能够对进程进行优先级设置,资源的计量以及资源的控制(比如:将进程挂起和恢复等操作)。

验证系统 cgroups

Cgroups在内核层默认已经开启,从Centos和Ubuntu不同版本对比,显然内核较新的支持的功能更多。
Centos7.4 cgroups:

[root@jk-k8s ~]# cat /etc/redhat-release

CentOS Linux release 7.4.1708 (Core)

[root@jk-k8s ~]#

[root@jk-k8s ~]# grep CGROUP /boot/config-3.10.0-693.el7.x86_64

CONFIG_CGROUPS=y

# CONFIG_CGROUP_DEBUG is not set

CONFIG_CGROUP_FREEZER=y

CONFIG_CGROUP_PIDS=y

CONFIG_CGROUP_DEVICE=y

CONFIG_CGROUP_CPUACCT=y

CONFIG_CGROUP_HUGETLB=y

CONFIG_CGROUP_PERF=y

CONFIG_CGROUP_SCHED=y

CONFIG_BLK_CGROUP=y

# CONFIG_DEBUG_BLK_CGROUP is not set

CONFIG_NETFILTER_XT_MATCH_CGROUP=m

CONFIG_NET_CLS_CGROUP=y

CONFIG_NETPRIO_CGROUP=y

[root@jk-k8s ~]#

cgroups中内存模块

[root@jk-k8s ~]# grep MEMCG /boot/config-3.10.0-693.el7.x86_64

CONFIG_MEMCG=y

CONFIG_MEMCG_SWAP=y

CONFIG_MEMCG_SWAP_ENABLED=y

CONFIG_MEMCG_KMEM=y
cgroups具体实现
  • blkio:块设备IO限制
  • cpu:使用调度程序为cgroup任务提供CPU访问
  • cpuacct:产生cgroup任务的CPU资源报告
  • cpuset:如果是多核心的cpu,这个子系统会为cgroup任务分配单独的cpu和内存
  • devices:允许或拒绝cgroup任务对设备访问
  • freezer:暂停和恢复cgroup任务
  • memory:设置每个cgroup的内存限制以及产生内存资源报告
  • net_cls:标记每个网络包以供cgroup方便使用
  • ns:命名空间子系统
  • perf_event:增加了对每group的检测跟踪的能力,可以检测属于某个特定的group的所有线程以及运行在特定CPU上的线程
查看系统cgroups
[root@jk-k8s ~]# ll /sys/fs/cgroup/

总用量 0

drwxr-xr-x 5 root root  0 819 09:46 blkio

lrwxrwxrwx 1 root root 11 819 09:46 cpu -> cpu,cpuacct

lrwxrwxrwx 1 root root 11 819 09:46 cpuacct -> cpu,cpuacct

drwxr-xr-x 5 root root  0 819 09:46 cpu,cpuacct

drwxr-xr-x 3 root root  0 819 09:46 cpuset

drwxr-xr-x 5 root root  0 819 09:46 devices

drwxr-xr-x 3 root root  0 819 09:46 freezer

drwxr-xr-x 3 root root  0 819 09:46 hugetlb

drwxr-xr-x 5 root root  0 819 09:46 memory

lrwxrwxrwx 1 root root 16 819 09:46 net_cls -> net_cls,net_prio

drwxr-xr-x 3 root root  0 819 09:46 net_cls,net_prio

lrwxrwxrwx 1 root root 16 819 09:46 net_prio -> net_cls,net_prio

drwxr-xr-x 3 root root  0 819 09:46 perf_event

drwxr-xr-x 3 root root  0 819 09:46 pids

drwxr-xr-x 5 root root  0 819 09:46 systemd

[root@jk-k8s ~]#

[root@jk-k8s ~]# cat /sys/fs/cgroup/cpu/docker/5a1b43275caa1f8c9fff9ea8ccd3813d4a25acf698f15a3ec5eacd77948833b5/cpuacct.usage

109845268

[root@jk-k8s ~]#

[root@jk-k8s ~]# cat /sys/fs/cgroup/memory/docker/5a1b43275caa1f8c9fff9ea8ccd3813d4a25acf698f15a3ec5eacd77948833b5/memory.limit_in_bytes

9223372036854771712

[root@jk-k8s ~]# cat /sys/fs/cgroup/memory/docker/5a1b43275caa1f8c9fff9ea8ccd3813d4a25acf698f15a3ec5eacd77948833b5/memory.max_usage_in_bytes

12566528

[root@jk-k8s ~]#

容器管理工具

LXC

官网:https://linuxcontainers.org
Linux Container 可以提供轻量级的虚拟化功能,以便隔离进程和资源,包括一系列容器的管理工具软件,如,lxc-create,lxc-start,lxc-attach等,但这技术功能不完善,目前较少使用。

docker

docker相当于增强版的LXC,功能更为强大和易用,也是当前最主流的容器前端管理工具
docker先启动一个容器也需要一个外部模板,也称为镜像,docker的镜像可以保存在一个公共的地方共享使用,只要把镜像下载下来就可以使用,最主要的是可以在镜像基础之上做自定义配置并且可以再把其提交为一个镜像,一个镜像可以被启动为多个容器。
docker的镜像是分层的,镜像底层为库文件且只读层即不能写入也不能删除数据,从镜像加载启动为一个容器后会生成一个可写层,其写入的数据会复制到宿主机上对应容器的目录,但是容器内的数据在删除容器后也会被随之删除。

pouch

https://github.com/alibaba/pouch
Pouch(小袋子)起源于2011年,并于2017年11月19日上午,在中国开源年会现场,阿里巴巴正式开源了基于Apache2.0协议的容器技术Pouch。Pouch是一款轻量级的容器技术,拥有快速高效、可移植性高、资源占用少等特性,主要帮助阿里更快的做到内部业务的交付,同时提高超大规模下数据中心的物理资源利用率
目前的容器方案大多基于Linux内核提供的cgroup和namespace来实现隔离,然后这样轻量级方案存在弊端:

  • 容器间,容器与宿主机间,共享一个内核
  • 内核实现的隔离资源,维度不足

面对如此的内核现状,阿里巴巴采取了三个方面的工作,来解决容器的安全问题:

  • 增强容器的隔离维度,比如网络带宽、磁盘使用量
  • 给内核提交patch,修复容器的资源可见性问题,cgroup方面的bug
  • 实现基于Hypervisor的容器,通过创建新内核来实现容器隔离
Podman

https://podman.io
虽然目前docker是管理Linux容器最好的耳工具,注意没有之一,但是podman的横空出现即将改变这一点
什么是Podman?
Podman即Pod Manager tool,从名称上可以看出和kubernets的pod的密切联系,不过就其功能来说,简言之:alias docker = podman,是centos8新集成的功能,或许不就的未来会替代docker
Podman是一个为Kubernetes而生的开源的容器管理工具,原来是CRI-O(即容器运行时接口CRI和开放容器计划OCI)项目的一部分,后来被分离成一个单独的项目叫libpod。其可在大多数Linux平台上使用,它是一种无守护程序的容器引擎,用于在Linux系统上开发,管理和运行任何符合Open Container Initiative(OCI)标准的容器和容器镜像。
Podman提供了一个与docker兼容的命令前端,Podman里面87%的指令都和docker cli相同,因此可以简单地为docker cli别名,即“alias docker = podman”,事实上,podman使用的一些库也是docker的一部分。

Podman和docker不同之处
  • docker需要在系统上运行一个守护进程(docker daemon),这会产生一定的开销,而podman不需要
  • 启动容器的方式不同: docker cli 命令通过 API 跟 docker engine(引擎)交互告诉它我想创建一个 container,然后 docker engine 才会调用 OCI containner runtime(runc) 来启动一个container。这代表container的process(进程)不会是docker cli 的chlid process(子进程)而是Docker Engine 的 child process。Podman是直接给OCI container runtime(runc)进行交互来创建container的,所以container process 直接是podman的child process。
  • 因为docker有docker daemon,所以docker启动的容器支持 –restart策略,但是podman不支持
  • docker需要使用root用户来创建容器,这可能会产生安全风向,尤其是当用户知道docker run命令的 –privileged选项时。podman既可以由root用户运行,也可以由非特权用户运行
  • docker在Linux上作为守护进程运行扼杀了容器社区的创新。如果要更改容器的工作方式,则需要更改docker守护程序并将这些更改推送到上游。没有守护进程,容器基础结构更加模块化,更容易进行更改。podman的无守护进程架构更加灵活和安全。

Docker的优势

  • 快速部署:短时间内可以部署成百上千个应用,更快速交付到线上
  • 高效虚拟化:不需要额外hypervisor支持,基于Linux内核实现应用虚拟化,相比虚拟机大幅提高性能和效率
  • 节省开支:提高服务器利用率,降低IT支持
  • 简化配置:将运行环境打包保存至容器,使用时直接启动即可
  • 环境统一:将开发,测试,生产的应用运行环境进行标准化统一,减少环境不一样带来的各种问题
  • 快速迁移和扩展:可实现跨平台运行物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台
  • 更好的实现面向服务的架构,推荐一个容器只运行一个应用,实现分布的应用模型,可以方便的进行横向扩展,符合开发中高内聚,低耦合的要求,减少不同服务器之间的相互影响

Docker的缺点

  • 多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底
  • 由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和繁琐
  • 如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重复浪费

容器的核心技术

容器规范

OCI官网:https://opencontainers.org
容器技术除了docker之外,还有coreOS的rkt,还有阿里的Pouch,为了保证容器生态的标准性和健康可持续发展,包括Linux基金会、Docker、微软、红帽、谷歌和IBM等公司在2015年6月共同成立了一个叫Open Container Initiative(OCI)的组织,其目的就是制定开放的标准的容器规范,目前OCI一共发布了两个规范,分别是runtime spec和image format spec,有了这两个规范,不同的容器公司开发的容器只要兼容这两个规范,就可以保证容器的可移植性和相互可操作性性。

容器runtime

runtime是真正运行容器的地方,因此为了运行不同的容器runtime需要和操作系统内核紧密合作相互在支持,以便为容器提供相应的运行环境
runtime类型:

  • LXC:Linux上早期的runtime,在2013年docker刚发布的时候,就是采用lxc作为runtime,docker把lxc复杂的容器创建与使用方式简化为docker自己的一套命令体系。随着docker的发展,原有的lxc不能满足docker的需求,比如跨平台功能
  • Libcontainer:随着docker的不断发展,重新定义容器的实现标准,将底层实现都抽象化到Libcontainer的接口。这就意味着,底层容器的实现方式变成了一种可变的方案,无论是使用namespace、cgroups技术抑或是使用systemd等其他方案,只要实现了Lincontainer定义的一组接口,docker都可以运行。这也为docker实现全面的跨平台带来了可能。
  • runc:早期libcontainer是docker公司控制的一个开源项目,OCI的成立后,docker把libcontainer项目移交给了OCI组织,runc就是在libcontainer的基础上进化而来,是目前docker默认的runtime,runc遵守OCI规范
  • rkt:是CoreOS开发的容器runtime,也符合OCI规范,所以使用rktruntime也可以运行docker容器
容器管理工具

管理工具连接runtime与用户,对用户提供图形或命令方式操作,然后管理工具将用户操作传递给runtime执行。

  • lxc是lxd的管理工具
  • Runc的管理工具是docker engine,docker engine包含后台deamon和cli两部分,大家经常提到的docker就是指的docker engine
  • rkt的管理工具是 rkt cli
容器定义工具

容器定义工具允许用户定义容器的属性和内容,以方便容器能够被保存、共享和重建。
Docker image:是docker容器的模板,runtime依据docker image创建容器
Dockerfile:包含N个命令的文本文件,通过dockerfile创建出docker image
ACI(App container image):与docker image类似,是CoreOS开发的rkt容器的镜像格式

镜像仓库

统一保存镜像而且是多个不同镜像版本的地方,叫做镜像仓库

  • Docker hub:docker官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接使用
  • 阿里云,网易等第三方镜像的公共仓库
  • Image registry:docker官方提供的私有仓库部署工具,无web管理界面,目前使用较少
  • Harbor:vmware提供自带web界面自带认证功能的镜像私有仓库,目前有很多公司使用
容器编排工具

当多个容器在多个主机运行的时候,单独管理容器是相当复杂而且很容易出错,而且也无法实现某一台主机宕机后容器自动迁移到其他主机从而实现高可用的目的,也无法实现动态伸缩功能,因此需要有一种工具可以实现统一管理、动态伸缩、故障自愈、批量执行等功能,这就是容器编排引擎
容器编排通常包括容器管理、调度、集群定义和服务发现等功能

  • Docker compose:docker官方实现单机容器的编排工具
  • Docker swarm:docker官方开发的容器编排引擎,支持overlay network
  • Mesos+Marathon:Mesos是Apache下的开源分布式资源管理框架,它被称为是分布式系统的内核。Mesos最初是由加州大学伯克利分校的AMPLab开发的,后在Twitter得到广泛使用。通用的集群组员调度平台,Mesos(资源分配)与marathon(容器编排平台)一起提供容器编排引擎功能
  • Kubernetes:Google领导开发的容器编排引擎,内部项目为Borg,且其同时支持docker和CoreOS,当前已成为容器编排工具的标准
docker依赖的技术
容器网络

docker自带的网络docker network仅支持管理单机的容器网络,当多主机运行的时候需要使用第三方开源网络,例如:calico、flannel等

服务发现

容器的动态扩容特性决定了容器IP也会随之变化,因此需要有一种机制开源自动识别并将用户请求动态转发到新创建的容器上,Kubernetes自带服务发现功能,需要结合kube-dns服务解析内部域名

容器监控

可以通过原生命令docker ps/top/stats查看容器运行状态,另外可以使用prometheus、heapster等第三方监控工具监控容器的运行状态

数据管理

容器的动态迁移会导致其在不同的host之前迁移,因此如何保证与容器相关的数据也能随之迁移或随时访问,可以使用逻辑卷/存储挂载等方式解决

日志收集

docker原生的日志查看工具docker logs,但是容器内部的日志需要通过ELK等专门的日志收集分析和展示工具进行处理

Docker安装及基础命令介绍

Docker安装准备

https://www.docker.com
OS版本的选择:
docker目前支持多种操作系统的安装运行,如Centos,Ubuntu,Redhat,Debian,Fedora,Mac,Windows,在Linux系统上需要内核版本在3.10或以上
docker版本选择:
docker版本号之前一直是0.x版本或1.x版本,从2017年3月1号开始改为每个季度发布一次稳定版,其版本号规则也统一变更为YY.MM,例如20.10表示2020年10月发布的
docker之前没有区分版本,但是2017年推出(将docker更名为)新的项目Moby,github地址:https://github.com/moby/moby ,Moby项目属于Docker项目全新上游,docker将是一个隶属于Moby的子产品,而且之后的版本开始区分CE(Docker Community Edition,社区版本)和EE(Docker Enterprise Edition,企业收费版),CE社区版和EE企业版都是每个季度发布一个新版本,但是EE版提供后期安全维护1年,而CE版是4个月。

安装和删除方法

官方文档:https://docs.docker.com/engine/install/
阿里云文档:https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.3e221b11guHCWE

Centos安装和删除docker

官方文档:https://docs.docker.com/engine/install/centos/
CentOS 6 因内核太旧,即使支持安装docker,但会有各种问题,不建议安装
CentOS 7的extras源虽然可以安装docker,但包比较旧,建议从官方源或镜像源站点下载安装docker
CentOS 8 有新技术podman代替docker
因此建议在CentOS 7 上安装 docker

# extras 源中包名为docker

[root@centos7 ~]# yum list docker

已加载插件:fastestmirror

Loading mirror speeds from cached hostfile

 * base: mirrors.bupt.edu.cn

 * extras: mirrors.neusoft.edu.cn

 * updates: mirrors.nju.edu.cn

可安装的软件包

docker.x86_64                                 2:1.13.1-209.git7d71120.el7.centos                                  extras
下载rpm包安装

官方rpm包下载地址:https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
阿里镜像下载地址:https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/

通过yum源安装:

由于官网yum源太慢,下面使用阿里云的yum源进行安装

rm -rf /etc/yum.repos.d/*



# centos 7 安装docker依赖三个yum源:Base,Extras,docker-ce

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo



yum clean all

yum install docker-ce -y

systemctl enable --now docker
删除docker
yum remove docker-ce



# 删除docker资源存放的相关文件

rm -ef /var/lib/docker
Docker 程序环境

Centos7 查看docker相关文件

[root@centos ~]# rpm -ql docker-ce

/usr/bin/docker-init

/usr/bin/docker-proxy

/usr/bin/dockerd

/usr/lib/systemd/system/docker.service

/usr/lib/systemd/system/docker.socket

[root@centos ~]#

[root@centos ~]# rpm -ql docker-ce

/usr/bin/docker-init

/usr/bin/docker-proxy

/usr/bin/dockerd

/usr/lib/systemd/system/docker.service

/usr/lib/systemd/system/docker.socket

[root@centos ~]#

[root@centos ~]# rpm -ql docker-ce-cli

/usr/bin/docker

/usr/libexec/docker/cli-plugins/docker-app

/usr/libexec/docker/cli-plugins/docker-buildx

/usr/share/bash-completion/completions/docker

/usr/share/doc/docker-ce-cli-20.10.17

/usr/share/doc/docker-ce-cli-20.10.17/LICENSE

/usr/share/doc/docker-ce-cli-20.10.17/MAINTAINERS

/usr/share/doc/docker-ce-cli-20.10.17/NOTICE

/usr/share/doc/docker-ce-cli-20.10.17/README.md

/usr/share/fish/vendor_completions.d/docker.fish

/usr/share/man/man1/docker-attach.1.gz

/usr/share/man/man1/docker-build.1.gz

/usr/share/man/man1/docker-builder-build.1.gz

/usr/share/man/man1/docker-builder-prune.1.gz

/usr/share/man/man1/docker-builder.1.gz

/usr/share/man/man1/docker-checkpoint-create.1.gz

/usr/share/man/man1/docker-checkpoint-ls.1.gz

/usr/share/man/man1/docker-checkpoint-rm.1.gz

/usr/share/man/man1/docker-checkpoint.1.gz

/usr/share/man/man1/docker-commit.1.gz

/usr/share/man/man1/docker-config-create.1.gz

/usr/share/man/man1/docker-config-inspect.1.gz

/usr/share/man/man1/docker-config-ls.1.gz

/usr/share/man/man1/docker-config-rm.1.gz

/usr/share/man/man1/docker-config.1.gz

/usr/share/man/man1/docker-container-attach.1.gz

/usr/share/man/man1/docker-container-commit.1.gz

/usr/share/man/man1/docker-container-cp.1.gz

/usr/share/man/man1/docker-container-create.1.gz

/usr/share/man/man1/docker-container-diff.1.gz

/usr/share/man/man1/docker-container-exec.1.gz

/usr/share/man/man1/docker-container-export.1.gz

/usr/share/man/man1/docker-container-inspect.1.gz

/usr/share/man/man1/docker-container-kill.1.gz

/usr/share/man/man1/docker-container-logs.1.gz

/usr/share/man/man1/docker-container-ls.1.gz

/usr/share/man/man1/docker-container-pause.1.gz

/usr/share/man/man1/docker-container-port.1.gz

/usr/share/man/man1/docker-container-prune.1.gz

/usr/share/man/man1/docker-container-rename.1.gz

/usr/share/man/man1/docker-container-restart.1.gz

/usr/share/man/man1/docker-container-rm.1.gz

/usr/share/man/man1/docker-container-run.1.gz

/usr/share/man/man1/docker-container-start.1.gz

/usr/share/man/man1/docker-container-stats.1.gz

/usr/share/man/man1/docker-container-stop.1.gz

/usr/share/man/man1/docker-container-top.1.gz

/usr/share/man/man1/docker-container-unpause.1.gz

/usr/share/man/man1/docker-container-update.1.gz

/usr/share/man/man1/docker-container-wait.1.gz

/usr/share/man/man1/docker-container.1.gz

/usr/share/man/man1/docker-context-create.1.gz

/usr/share/man/man1/docker-context-export.1.gz

/usr/share/man/man1/docker-context-import.1.gz

/usr/share/man/man1/docker-context-inspect.1.gz

/usr/share/man/man1/docker-context-ls.1.gz

/usr/share/man/man1/docker-context-rm.1.gz

/usr/share/man/man1/docker-context-update.1.gz

/usr/share/man/man1/docker-context-use.1.gz

/usr/share/man/man1/docker-context.1.gz

/usr/share/man/man1/docker-cp.1.gz

/usr/share/man/man1/docker-create.1.gz

/usr/share/man/man1/docker-diff.1.gz

/usr/share/man/man1/docker-events.1.gz

/usr/share/man/man1/docker-exec.1.gz

/usr/share/man/man1/docker-export.1.gz

/usr/share/man/man1/docker-history.1.gz

/usr/share/man/man1/docker-image-build.1.gz

/usr/share/man/man1/docker-image-history.1.gz

/usr/share/man/man1/docker-image-import.1.gz

/usr/share/man/man1/docker-image-inspect.1.gz

/usr/share/man/man1/docker-image-load.1.gz

/usr/share/man/man1/docker-image-ls.1.gz

/usr/share/man/man1/docker-image-prune.1.gz

/usr/share/man/man1/docker-image-pull.1.gz

/usr/share/man/man1/docker-image-push.1.gz

/usr/share/man/man1/docker-image-rm.1.gz

/usr/share/man/man1/docker-image-save.1.gz

/usr/share/man/man1/docker-image-tag.1.gz

/usr/share/man/man1/docker-image.1.gz

/usr/share/man/man1/docker-images.1.gz

/usr/share/man/man1/docker-import.1.gz

/usr/share/man/man1/docker-info.1.gz

/usr/share/man/man1/docker-inspect.1.gz

/usr/share/man/man1/docker-kill.1.gz

/usr/share/man/man1/docker-load.1.gz

/usr/share/man/man1/docker-login.1.gz

/usr/share/man/man1/docker-logout.1.gz

/usr/share/man/man1/docker-logs.1.gz

/usr/share/man/man1/docker-manifest-annotate.1.gz

/usr/share/man/man1/docker-manifest-create.1.gz

/usr/share/man/man1/docker-manifest-inspect.1.gz

/usr/share/man/man1/docker-manifest-push.1.gz

/usr/share/man/man1/docker-manifest-rm.1.gz

/usr/share/man/man1/docker-manifest.1.gz

/usr/share/man/man1/docker-network-connect.1.gz

/usr/share/man/man1/docker-network-create.1.gz

/usr/share/man/man1/docker-network-disconnect.1.gz

/usr/share/man/man1/docker-network-inspect.1.gz

/usr/share/man/man1/docker-network-ls.1.gz

/usr/share/man/man1/docker-network-prune.1.gz

/usr/share/man/man1/docker-network-rm.1.gz

/usr/share/man/man1/docker-network.1.gz

/usr/share/man/man1/docker-node-demote.1.gz

/usr/share/man/man1/docker-node-inspect.1.gz

/usr/share/man/man1/docker-node-ls.1.gz

/usr/share/man/man1/docker-node-promote.1.gz

/usr/share/man/man1/docker-node-ps.1.gz

/usr/share/man/man1/docker-node-rm.1.gz

/usr/share/man/man1/docker-node-update.1.gz

/usr/share/man/man1/docker-node.1.gz

/usr/share/man/man1/docker-pause.1.gz

/usr/share/man/man1/docker-plugin-create.1.gz

/usr/share/man/man1/docker-plugin-disable.1.gz

/usr/share/man/man1/docker-plugin-enable.1.gz

/usr/share/man/man1/docker-plugin-inspect.1.gz

/usr/share/man/man1/docker-plugin-install.1.gz

/usr/share/man/man1/docker-plugin-ls.1.gz

/usr/share/man/man1/docker-plugin-push.1.gz

/usr/share/man/man1/docker-plugin-rm.1.gz

/usr/share/man/man1/docker-plugin-set.1.gz

/usr/share/man/man1/docker-plugin-upgrade.1.gz

/usr/share/man/man1/docker-plugin.1.gz

/usr/share/man/man1/docker-port.1.gz

/usr/share/man/man1/docker-ps.1.gz

/usr/share/man/man1/docker-pull.1.gz

/usr/share/man/man1/docker-push.1.gz

/usr/share/man/man1/docker-rename.1.gz

/usr/share/man/man1/docker-restart.1.gz

/usr/share/man/man1/docker-rm.1.gz

/usr/share/man/man1/docker-rmi.1.gz

/usr/share/man/man1/docker-run.1.gz

/usr/share/man/man1/docker-save.1.gz

/usr/share/man/man1/docker-search.1.gz

/usr/share/man/man1/docker-secret-create.1.gz

/usr/share/man/man1/docker-secret-inspect.1.gz

/usr/share/man/man1/docker-secret-ls.1.gz

/usr/share/man/man1/docker-secret-rm.1.gz

/usr/share/man/man1/docker-secret.1.gz

/usr/share/man/man1/docker-service-create.1.gz

/usr/share/man/man1/docker-service-inspect.1.gz

/usr/share/man/man1/docker-service-logs.1.gz

/usr/share/man/man1/docker-service-ls.1.gz

/usr/share/man/man1/docker-service-ps.1.gz

/usr/share/man/man1/docker-service-rm.1.gz

/usr/share/man/man1/docker-service-rollback.1.gz

/usr/share/man/man1/docker-service-scale.1.gz

/usr/share/man/man1/docker-service-update.1.gz

/usr/share/man/man1/docker-service.1.gz

/usr/share/man/man1/docker-stack-deploy.1.gz

/usr/share/man/man1/docker-stack-ls.1.gz

/usr/share/man/man1/docker-stack-ps.1.gz

/usr/share/man/man1/docker-stack-rm.1.gz

/usr/share/man/man1/docker-stack-services.1.gz

/usr/share/man/man1/docker-stack.1.gz

/usr/share/man/man1/docker-start.1.gz

/usr/share/man/man1/docker-stats.1.gz

/usr/share/man/man1/docker-stop.1.gz

/usr/share/man/man1/docker-swarm-ca.1.gz

/usr/share/man/man1/docker-swarm-init.1.gz

/usr/share/man/man1/docker-swarm-join-token.1.gz

/usr/share/man/man1/docker-swarm-join.1.gz

/usr/share/man/man1/docker-swarm-leave.1.gz

/usr/share/man/man1/docker-swarm-unlock-key.1.gz

/usr/share/man/man1/docker-swarm-unlock.1.gz

/usr/share/man/man1/docker-swarm-update.1.gz

/usr/share/man/man1/docker-swarm.1.gz

/usr/share/man/man1/docker-system-df.1.gz

/usr/share/man/man1/docker-system-events.1.gz

/usr/share/man/man1/docker-system-info.1.gz

/usr/share/man/man1/docker-system-prune.1.gz

/usr/share/man/man1/docker-system.1.gz

/usr/share/man/man1/docker-tag.1.gz

/usr/share/man/man1/docker-top.1.gz

/usr/share/man/man1/docker-trust-inspect.1.gz

/usr/share/man/man1/docker-trust-key-generate.1.gz

/usr/share/man/man1/docker-trust-key-load.1.gz

/usr/share/man/man1/docker-trust-key.1.gz

/usr/share/man/man1/docker-trust-revoke.1.gz

/usr/share/man/man1/docker-trust-sign.1.gz

/usr/share/man/man1/docker-trust-signer-add.1.gz

/usr/share/man/man1/docker-trust-signer-remove.1.gz

/usr/share/man/man1/docker-trust-signer.1.gz

/usr/share/man/man1/docker-trust.1.gz

/usr/share/man/man1/docker-unpause.1.gz

/usr/share/man/man1/docker-update.1.gz

/usr/share/man/man1/docker-version.1.gz

/usr/share/man/man1/docker-volume-create.1.gz

/usr/share/man/man1/docker-volume-inspect.1.gz

/usr/share/man/man1/docker-volume-ls.1.gz

/usr/share/man/man1/docker-volume-prune.1.gz

/usr/share/man/man1/docker-volume-rm.1.gz

/usr/share/man/man1/docker-volume.1.gz

/usr/share/man/man1/docker-wait.1.gz

/usr/share/man/man1/docker.1.gz

/usr/share/man/man5/Dockerfile.5.gz

/usr/share/man/man5/docker-config-json.5.gz

/usr/share/man/man8/dockerd.8.gz

/usr/share/zsh/vendor-completions/_docker
Docker 命令帮助

官方文档:https://docs.docker.com/reference/
docker命令是最常使用的docker客户端命令,其后面可以加不同的参数以实现不同的功能

# docker 命令格式

# COMMAND 分为 

# Management Commands 指定管理员的资源对象类型,较新的命令用法,将命令按资源类型进行分类,方便使用

# Commands 对不同资源操作的命令不分类,使用容易产生混乱

docker [OPTIONS] COMMAND



# docker 命令有很多子命令,可以用下面方法查看帮助

# docker 命令帮助

man docker

docker

docker --help



# docker 子命令帮助

man docker -COMMAND

docker COMMAND --help
查看docker相关信息
查看docker版本
[root@centos ~]# docker version

Client: Docker Engine - Community

 Version:           20.10.17

 API version:       1.41

 Go version:        go1.17.11

 Git commit:        100c701

 Built:             Mon Jun  6 23:05:12 2022

 OS/Arch:           linux/amd64

 Context:           default

 Experimental:      true



Server: Docker Engine - Community

 Engine:

  Version:          20.10.17

  API version:      1.41 (minimum version 1.12)

  Go version:       go1.17.11

  Git commit:       a89b842

  Built:            Mon Jun  6 23:03:33 2022

  OS/Arch:          linux/amd64

  Experimental:     false

 containerd:

  Version:          1.6.7

  GitCommit:        0197261a30bf81f1ee8e6a4dd2dea0ef95d67ccb

 runc:

  Version:          1.1.3

  GitCommit:        v1.1.3-0-g6724737

 docker-init:

  Version:          0.19.0

  GitCommit:        de40ad0
查看docker详细信息
[root@centos ~]# docker info
Client:
 Context:    default
 Debug Mode: false # client端是否开启debug
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.8.2-docker)
  scan: Docker Scan (Docker Inc., v0.17.0)

Server:
 Containers: 0 # 当前主机运行的容器总数
  Running: 0	 # 正在运行的容器个数
  Paused: 0	   # 暂停的容器个数
  Stopped: 0   # 停止的容器个数
 Images: 0     # 当前服务器的镜像个数
 Server Version: 20.10.17    # 服务端版本
 Storage Driver: overlay2    # 正在使用的存储引擎
  Backing Filesystem: xfs    # 后端文件系统,即服务器的磁盘文件系统
  Supports d_type: true      # 是否支持 d_type
  Native Overlay Diff: true  # 是否支持差异数据存储
  userxattr: false
 Logging Driver: json-file   # 日志类型
 Cgroup Driver: cgroupfs		 # Cgroups类型
 Cgroup Version: 1
 Plugins:										 # 插件
  Volume: local							 # 卷
  Network: bridge host ipvlan macvlan null overlay    # overlay 跨主机通信
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog # 日志类型
 Swarm: inactive						 # 是否支持 swarm
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc       # 默认使用的容器运行时
 Init Binary: docker-init    # 初始化容器的守护进程,即pid为1的进程
 containerd version: 0197261a30bf81f1ee8e6a4dd2dea0ef95d67ccb # 版本
 runc version: v1.1.3-0-g6724737	# runc版本
 init version: de40ad0			 # init 版本
 Security Options:           # 安全选项
  seccomp                    # 安全计算模块,即制容器操作
   Profile: default					 # 默认的配置文件
 Kernel Version: 3.10.0-693.el7.x86_64    # 宿主机内核版本
 Operating System: CentOS Linux 7 (Core)  # 宿主机操作系统
 OSType: linux														# 宿主机操作系统类型
 Architecture: x86_64											# 宿主机架构
 CPUs: 2																	# 宿主机CPU数量
 Total Memory: 1.792GiB										# 宿主机总内存
 Name: centos															# 宿主机 hostname
 ID: E66M:LPI3:YB2Z:LJKN:LNB2:P7Z3:6HYX:DSFF:KISM:SSJX:PVIF:B2ZM  # 宿主机 ID
 Docker Root Dir: /var/lib/docker				# 宿主机关于docker数据的保存目录
 Debug Mode: false											# server 端是否开启debug
 Registry: https://index.docker.io/v1/	# 仓库路径
 Labels:
 Experimental: false										# 是否是测试版
 Insecure Registries:	
  127.0.0.0/8														# 非安全的镜像库
 Live Restore Enabled: false            # 是否开启活动重启 (重启docker-daemon 不关闭容器)
查看docker0网卡

在docker安装启动后,默认会生成一个名称为docker0的网卡且默认IP地址为172.17.0.1

Docker存储引擎
  • AUFS是一种UnionFs,是文件级的存储驱动。Aufs是之前的UnionFS的重新实现,2006年由JunjiroOkajima开发,所谓UnionFS就是把不同物理位置的目录合并mount到同一个目录中。简单来说就是支持将不同目录挂载到一个虚拟文件系统下。这种可以层层地叠加修改文件。无论底下有多少都是只读的,最上系统可写的。当需要修改一个文件时,AUFS常见该文件的一个副本,使用CoW将文件从只读层复制到可写进行修改,结果也保存在Docker中,底下的只读层就是image,可写层就是Container。aufs被拒绝合并到主线Linux。其代码被批评为“dense,unreadable,uncommented 密集、不可读、未注释”。相反,OverlayFS被合并到Linux内核中。在多次尝试将aufs合并到主线内核失败后,作者放弃了AUFS是docker18.06及更早版本的首选存储驱动程序,在内核3.13上运行ubuntu14.04时不支持overlay2
  • Overlay:一种UnionFS文件系统,Linux内核3.18后支持
  • Overlay2:Overlay的升级版,到目前为止,所有Linux发行版推荐使用的存储类型,也是docker默认使用的存储引擎为overlay2,需要磁盘分区支持d-type功能,因此需要系统磁盘的额外支持,相对AUFS来说Overlay2有以下优势:更简单的设计;从3.18开始就进入了Linux内核主线;资源消耗更少
  • devicemapper:因为Centos7.2和RHEL7.2的之前版本内核版本不支持overlay2,默认使用的存储驱动程序,最大数据容量只支持100G且性能不佳,当前较新版本的CentOS已经支持overlay2,因此推荐使用overlay2,另外此存储引擎已在Docker Engine 18.09中弃用
  • ZFS(Sun-2005)/btrfs(Oracle-2007):目前没有广泛使用
  • VFS:用于测试环境,适用于无法使用copy-on-write时的情况。此存储驱动程序的性能很差,通常不建议用于生产

Docker官方推荐首选存储引擎为overlay2,其次为devicemapper,但是devicemapper存在使用空间方面的一些限制,虽然可以通过后期配置解决,但是官方依然推荐使用overlay2,以下是生产故障示例:https://www.cnblogs.com/youruncloud/p/5736718.html

docker服务进程

通过查看docker进程,了解docker的运行及工作方式

docker的进程关系

docker相关的四个进程:

  • dockerd:服务器程序,被client直接访问,其父进程为宿主机的systemd守护进程
  • docker-proxy:每个进程docker-proxy实现对应一个需要网络通信的容器,管理宿主机和容器之间端口映射,其父进程为dockerd,如果容器不需要网络则无需启动
  • containerd:被dockerd进程调用以实现与runc交互
  • containerd-shim:真正运行容器的载体,每个容器对应一个containerd-shim进程,其父进程为containerd
容器的创建与管理过程

通信流程:

1.dockerd通过grpc和containerd模块通信,dockerd由libcontainerd负责和containerd进行交换,docker和containerd通信socket文件:/run/containerd/containerd.sock
2.containerd在docker启动时被启动,然后containerd启动grpc请求监听,containerd处理grpc请求,根据请求做相应动作
3.若是run,start或是exec容器,containerd拉起一个container-shim,并进行相应的操作
4.container-shim被拉起后,start/exec/create拉起runc进程,通过exit、control文件和containerd通信,通过父子进程关系和SIGCHLD监控容器中进程状态
5.在整个容器生命周期中,container通过epoll监控容器文件,监控容器事件

gRPC简介

官网:https://www.grpc.io

gRPC是Google开发的一款高性能、开源和通用的RPC框架,支持众多语言客户端

Docker 服务管理

docker服务基于C/S结构,可以实现基于本地和远程方式进行管理

# Dockerd守护进程启动选项
-H tcp://host:port
	 unix:///path/to/socket,
	 fd://* or fd://socketfd