什么是docker
Docker is an open platform for developing,shipping, and running applications.
Docker是PaaS提供商dotCloud开源的基于LXC的,源代码托管在Github上的,基于go语言开发的,遵循Appache2.0协议的容器引擎。
Docker允许打包程序并附带它所有的依赖成标准化的单元来进行部署软件。
Docker具有轻量、开源、安全的特点。
Docker VS VM
Docker容器在资源隔离和可配额方面与VM相似,但是不同于 VM的架构,使Docker容易更便携和高效。
VM架构
一个VM包含有应用、必要的二进制文件与库和一个完整的操作系统,以上所有加起可能有几十G的大小。
Containers架构
Containers包含应用和它所有的依赖,但是与其它containers共享内核。像用户空间独立的进程一样运行在主机操作系统上。Docker容器并不是只能运行在特定的架构上,可以运行在任何计算机、任何架构和任何云上。
理解Docker架构
Docker可以用来干什么
1、快速交付应用
2、部署和扩展更容易
3、实现更高密度和运行更多负载
Docker重要组件
Docker:开源的容器化平台
DockerHub:共享和管理docker容器的SaaS平台
Docker架构
Docker采用C/S架构,Docker客户端与进行创建、运行和分发容器的Docker守护进程进行会话。Docker客户端和Docker守护进程可以运行在同一系统,或者通过Docker客户端连接到远端Docker守护进程。Docker客户端和Docker守护进程通过sockets或RESTful API进行通信。
Docker daemon
如上图所示,Docker daemon运行在一台主机上。用户并不是直接与docker deamon进行通信,而是通过Docker client。
Docker client
docker二进制形式的Docker client是连接Docker的基本用户接口。它接收来自客户端的命令和与Docker daemon之间的会话。
Docker内部
Docker镜像(building)
Docker镜像是一个只读的模版,它可能是一个带有apache的CentOS操作系统。Docker镜像是用来创建Docker容器的,因此,Docker镜像是Docker的build组件。
Docker仓库(distributing)
Docker仓库是存储镜像的。是上传或下载镜像公共的或私有的仓库。公共的仓库由Docker Hub提供。因此Docker registries是Docker的distribution组件。
Docker containers(running)
Docker容器和目录很相似。一个Docker容器包含一个应用程序运行的所需的东西。每个Docker容器都是使用Docker image创建的,可以运行、启动、停止、移动和删除。每个Docker容器都是一个独立和安全的应用平台。因此,Docker containers是Docker的run组件
Docker使用的技术
LXC
LXC如何实现虚拟化
前面说过,Docker是基于LXC的操作系统级别的虚拟化。因此可以从以下几个方面理解Docker是如何实现虚拟化的。
1、隔离型
LXC是通过container,具体是通过kerner namespace实现的
2、可配额
LXC是通过cgroups来控制资源的
3、移动性
Docker利用AUFS实现
4、安全性
对于LXC,用户的进程是lxc-start进程的子进程,只是在kernel的namespace中隔离的,因此需要一些kernel的patch来保证用户的运行环境不受来自host主机的恶意入侵。dotCloud主要利用Kernel grsecpatch解决的
命名空间(namespace)
LXC能够实现隔离型,主要是靠kernel的namespace,期中的pid、net、ipc、mnt、uts等namespace将container的进程、网络、消息、文件系统和host隔离开的。
pid namespace
不同用户的进程就是通过pid namespace隔离开的。不同的namespace可以有相同的pid namespace。具有以下特征
1、每个 namespace 中的 pid 是有自己的 pid=1 的进程(类似 /sbin/init 进程)
2、每个 namespace 中的进程只能影响自己的同一个 namespace 或子 namespace 中的进程
3、因为 /proc 包含正在运行的进程,因此在 container 中的 pseudo-filesystem 的 /proc 目录只能看到自己 namespace 中的进程
4、因为 namespace 允许嵌套,父 namespace 可以影响子 namespace 的进程,所以子 namespace 的进程可以在父 namespace 中看到,但是具有不同的 pid
uts namespace
UTS (“UNIX Time-sharing System”)namespace 允许每个 container 拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 Host 上的一个进程。
net namespace
网络隔离是通过 net namespace 实现的,每个 net namespace 有独立的network
devices, IP addresses, IP routingtables, /proc/net 目录。这样每个 container 的网络
就能隔离开来。 docker 默认采用 veth 的方式将 container 中的虚拟网卡同 host 上的
一个 docker bridge 连接在一起。
mnt namespace
类似chroot,将一个进程放到一个特定的目录执行。mnt namespace允许不同
namespace的进程看到的文件结构不同,这样每个namespace 中的进程所看到的文件目录就被隔离开了。同chroot不同,每个namespace中的container在/proc/mounts的信息只包含所在namespace的mount point。
ipc namespace
container 中进程交互还是采用 Linux 常见的进程间交互方法 (interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不同,container 的进程间交互实际上还是 host 上具有相同 pid namespace 中的进程间交互,因此需要在IPC资源申请时加入 namespace 信息 - 每个 IPC 资源有一个唯一的32bit ID。
user namespace
每个 container 可以有不同的 user 和 group id, 也就是说可以以 container 内部的用户在 container 内部执行程序而非 Host 上的用户。
有了以上 6 种 namespace 从进程、网络、IPC、文件系统、UTS 和用户角度的隔离,一个 container 就可以对外展现出一个独立计算机的能力,并且不同 container从 OS 层面实现了隔离。 然而不同 namespace 之间资源还是相互竞争的,仍然需要类似 ulimit 来管理每个 container 所能使用的资源
资源配额-Control Groups
cgroups 实现了对资源的配额和度量。 cgroups 的使用非常简单,提供类似文件的接口,在 /cgroup 目录下新建一个文件夹即可新建一个 group,在此文件夹中新建 task 文件,并将 pid 写入该文件,即可实现对该进程的资源控制。具体的资源配置选项可以在该文件夹中新建子 subsystem ,{子系统前缀}.{资源项} 是典型的配置方法, 如 memory.usage_in_bytes 就定义了该 group 在 subsystem memory 中的一个内存限制选项。另外,cgroups 中的 subsystem 可以随意组合,一个 subsystem 可以在不同的 group 中,也可以一个 group 包含多个 subsystem - 也就是说一个 subsystem。
1、memory
内存相关的限制
2、cpu
在 cgroup 中,并不能像硬件虚拟化方案一样能够定义 CPU 能力,但是能够定义 CPU 轮转的优先级,因此具有较高 CPU 优先级的进程会更可能得到 CPU 运算。 通过将参数写入 cpu.shares ,即可定义改 cgroup 的 CPU 优先级 - 这里是一个相对权重,而非绝对值
3、blkio
block IO 相关的统计和限制,byte/operation 统计和限制 (IOPS 等),读写速度限制等,但是这里主要统计的都是同步 IO
4、devices
设备权限限制
5、net_cls、cpuacct、freezer等其它管理项。
参考文献:
https://docs.docker.com/engine/understanding-docker/
https://www.docker.com/what-docker
linuxcontainers.org
http://tiewei.github.io/cloud/Docker-Getting-Start