为了更好地理解容器的特性,本节咱们将讨论容器的底层实现技术。
cgroup 和 namespace 是最重要的两种技术。cgroup 实现资源限额, namespace 实现资源隔离。docker
cgroup 全称 Control Group。Linux 操做系统经过 cgroup 能够设置进程使用 CPU、内存 和 IO 资源的限额。相信你已经猜到了:前面咱们看到的--cpu-shares
、-m
、--device-write-bps
实际上就是在配置 cgroup。网络
cgroup 到底长什么样子呢?咱们能够在 /sys/fs/cgroup 中找到它。仍是用例子来讲明,启动一个容器,设置 --cpu-shares=512
:学习
查看容器的 ID:spa
在 /sys/fs/cgroup/cpu/docker 目录中,Linux 会为每一个容器建立一个 cgroup 目录,以容器长ID 命名:操作系统
目录中包含全部与 cpu 相关的 cgroup 配置,文件 cpu.shares 保存的就是 --cpu-shares
的配置,值为 512。rest
一样的,/sys/fs/cgroup/memory/docker 和 /sys/fs/cgroup/blkio/docker 中保存的是内存以及 Block IO 的 cgroup 配置。code
在每一个容器中,咱们均可以看到文件系统,网卡等资源,这些资源看上去是容器本身的。拿网卡来讲,每一个容器都会认为本身有一块独立的网卡,即便 host 上只有一块物理网卡。这种方式很是好,它使得容器更像一个独立的计算机。进程
Linux 实现这种方式的技术是 namespace。namespace 管理着 host 中全局惟一的资源,并可让每一个容器都以为只有本身在使用它。换句话说,namespace 实现了容器间资源的隔离。内存
Linux 使用了六种 namespace,分别对应六种资源:Mount、UTS、IPC、PID、Network 和 User,下面咱们分别讨论。资源
Mount namespace
Mount namespace 让容器看上去拥有整个文件系统。
容器有本身的 /
目录,能够执行 mount
和 umount
命令。固然咱们知道这些操做只在当前容器中生效,不会影响到 host 和其余容器。
UTS namespace
简单的说,UTS namespace 让容器有本身的 hostname。 默认状况下,容器的 hostname 是它的短ID,能够经过 -h
或 --hostname
参数设置。
IPC namespace
IPC namespace 让容器拥有本身的共享内存和信号量(semaphore)来实现进程间通讯,而不会与 host 和其余容器的 IPC 混在一块儿。
PID namespace
咱们前面提到过,容器在 host 中以进程的形式运行。例如当前 host 中运行了两个容器:
经过 ps axf
能够查看容器进程:
全部容器的进程都挂在 dockerd 进程下,同时也能够看到容器本身的子进程。 若是咱们进入到某个容器,ps
就只能看到本身的进程了:
并且进程的 PID 不一样于 host 中对应进程的 PID,容器中 PID=1 的进程固然也不是 host 的 init 进程。也就是说:容器拥有本身独立的一套 PID,这就是 PID namespace 提供的功能。
Network namespace
Network namespace 让容器拥有本身独立的网卡、IP、路由等资源。咱们会在后面网络章节详细讨论。
User namespace
User namespace 让容器可以管理本身的用户,host 不能看到容器中建立的用户。
在容器中建立了用户 cloudman,但 host 中并不会建立相应的用户。
本章首先经过大量实验学习了容器的各类操做以及容器状态之间如何转换,而后讨论了限制容器使用 CPU、内存和 Block IO 的方法,最后学习了实现容器的底层技术:cgroup 和 namespace。
下面是容器的经常使用操做命令:
create 建立容器
run 运行容器
pause 暂停容器
unpause 取消暂停继续运行容器
stop 发送 SIGTERM 中止容器
kill 发送 SIGKILL 快速中止容器
start 启动容器
restart 重启容器
attach attach 到容器启动进程的终端
exec 在容器中启动新进程,一般使用 "-it" 参数
logs 显示容器启动进程的控制台输出,用 "-f" 持续打印
rm 从磁盘中删除容器
到这里,咱们已经学习完了容器章节。下一节开始讨论容器网络。