第2章Docker 的体系结构docker 使用 C/S 架构docker daemon 作为 server 端接受 client 的请求并处理创建、运行、分发容器他们可以运行在一个机器上也通过 sockerts 或者 RESTful API 通信Docker daemon 一般在宿主主机后台运行用户使用 client 而直接跟 daemon 交互。Docker client 以系统做 bin 命令的形式存在用户用 docker 命令来跟 docker daemon 交互。2.1、Docker内部组件docker 有三个内部组件 docker images docker registries docker containers2.1.1、Docker imagesdocker images 就是一个只读的模板。比如一个 image 可以包含一个 ubuntu 的操作系统里面安装了apache 或者你需要的应用程序。images 可以用来创建 docker containersdocker 提供了一个很简单的机制来创建 images 或者更新现有的 images你甚至可以直接从其他人那里下载一个已经做好的 images2.1.2、Docker registriesDocker registries 也叫 docker 仓库它有公有仓库和私有仓库 2 种形式他们都可以用来让你上传和下载 images。公有的仓库也叫 Docker Hub。它提供了一个巨大的 image 库可以让你下载你也可以在自己的局域网内建一个自己的私有仓库。2.1.3、Docker containersDocker containers 也叫 docker 容器容器是从 image 镜像创建的。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、安全的平台。2.2、Docker image 的工作原理每个 docker 都有很多层次构成docker 使用 union file systems 将这些不同的层结合到一个 image 中去。AUFS (AnotherUnionFS) 是一种 Union FS, 简单来说就是支持将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)的文件系统, 更进一步的理解, AUFS 支持为每一个成员目录(类似 Git Branch)设定 readonly、readwrite 和 whiteout-able 权限, 同时 AUFS 里有一个类似分层的概念, 对 readonly 权限的 branch 可以逻辑上进行修改(增量地, 不影响 readonly 部分的)。通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个 disk 挂到同一个目录下, 另一个更常用的就是将一个 readonly 的 branch 和一个 writeable 的 branch 联合在一起Live CD 正是基于此方法可以允许在 OS image 不变的基础上允许用户在其上进行一些写操作。Docker 在 AUFS 上构建的 container image 也正是如此。2.3、Docker 仓库docker 仓库用来保存我们的 images当我们创建了自己的 image 之后我们就可以使用 push 命令将它上传到公有或者私有仓库这样下次要在另外一台机器上使用这个 image 时候只需要从仓库上 pull 下来就可以了。2.4、Docker 容器当我们运行 docker run -i -t ubuntu /bin/bash 命令时docker 在后台运行的操作如下如果本地有 ubuntu 这个 image 就从它创建容器否则从公有仓库下载从 image 创建容器分配一个文件系统并在只读的 image 层外面挂载一层可读写的层从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去从地址池配置一个 ip 地址给容器执行你指定的程序在这里启动一个/bin/bash 进程-i -t 指定标准输入和输出2.5、Docker 底层技术docker 底层的 2 个核心技术分别是 Namespaces 和 Control groups以下内容摘自 InfoQ Docker自 1.20 版本开始 docker 已经抛开 lxc不过下面的内容对于理解 docker 还是有很大帮助。2.5.1、pid namespace不同用户的进程就是通过 pid namespace 隔离开的且不同 namespace 中可以有相同 pid。所有的 LXC 进程在 docker 中的父进程为 docker 进程每个 lxc 进程具有不同的 namespace。同时由于允许嵌套因此可以很方便的实现 Docker in Docker。2.5.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 连接在一起。2.5.3、ipc namespacecontainer 中进程交互还是采用 linux 常见的进程间交互方法(interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不同的是container 的进程间交互实际上还是 host 上具有相同 pid namespace 中的进程间交互因此需要在 IPC 资源申请时加入 namespace 信息 - 每个 IPC 资源有一个唯一的 32 位 ID。2.5.4、mnt namespace类似 chroot将一个进程放到一个特定的目录执行。mnt namespace 允许不同 namespace 的进程看到的文件结构不同这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同 chroot 不同每个 namespace 中的 container 在/proc/mounts 的信息只包含所在 namespace 的 mount point。2.5.5、uts namespaceUTS(“UNIX Time-sharing System”) namespace 允许每个 container 拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 Host 上的一个进程。2.5.6、user namespace每个 container 可以有不同的 user 和 group id, 也就是说可以在 container 内部用 container 内部的用户执行程序而非 Host 上的用户。