Docker 简述
什么是容器
当一个应用程序仅由较少数量的大组件构成时,完全可以接受给每个组件分配专用的虚拟机,以及通过给每个组件提供自己的操作系统实例来隔离它们的环境。但是当这些组件开始变小且数量开始增长时,如果你不想浪费硬件资源,又想持续压低硬件成本,那就不能给每个组件配置一个虚拟机了。
容器类似与虚拟机,但开销小很多。一个容器里运行的进程实际上运行在宿主机的操作系统上,就像所有其他进程一样,不像虚拟机,进程是运行在不同的操作系统上的。但在容器里的进程仍然是和其他进程隔离的。对于容器内进程本身而言,就好像是在机器和操作系统上运行的唯一一个进程。
容器隔离机制
容器实现隔离有两个机制:第一个是 Linux 命名空间,它使每个进程只看到它自己的系统视图;第二个是 cgroups,它限制了进程能使用的资源量。
用 Linux 命名空间隔离进程
每个 Linux 系统最初只有一个命名空间,所有的系统资源都属于这一个命名空间。一个进程在一个命名空间下运行,进程将只能看到同一个命名空间下的资源。通过 clone 函数可以在创建新进程的同时创建 namespace:
1 | int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL); |
在这里指定 CLONE_NEWPID 参数,这样新创建的进程,就会看到一个全新的进程空间。而此时这个新的进程,也就变成了 PID=1 的进程。
与 namespace 相关的 flag 参数有 CLONE_NEWNS、CLONE_NEWUTS、CLONE_NEWIPC、CLONE_NEWPID、CLONE_NEWNET 和 CLONE_NEWUSER,对应 Mount(mnt)、UTS、Inter-process communication(ipc)、Process ID(pid)、Network(net)、User ID(user) 这六种类型的命名空间。
用 cgroups 限制系统的可用资源
cgroups 是一个 Linux 内核功能,它用来限制一个进程或者一组进程的资源使用。一个进程的资源(CPU、内存、网络带宽等)使用量不能超过被分配的量。
cgroups 通过 cgroupfs 提供接口,cgroupfs 默认情况下挂载在 /sys/fs/cgroup 目录。
cgroups 限制 CPU、内存的简单操作方法:
1 | # 创建一个新的目录,也就是创建了一个新的 cgroup |
Docker 容器介绍
Docker 是第一个使容器在不同机器之间移植的系统。Docker 有三个概念:
- 镜像 —— Docker 镜像里包含了打包的应用程序及其所依赖的环境。
- 镜像仓库 —— Docker 镜像仓库用于存放 Docker 镜像。
- 容器 —— 一个运行中的容器是一个运行在 Docker 主机上的进程,但它和主机以及所有运行在主机上的其他进程都是隔离的。
Docker 推荐将容器运行时的 cgroup driver 更改为 systemd,systemd 限制 CPU、内存的简单操作方法:
1 | # 限制 CPU 占用为 0.1 个 CPU,内存为 200 MB |
systemd 相对 cgroupfs 更加简单,目前主流 Linux 发行版中 systemd 是系统自带的 cgroup 管理器,系统初始化就存在的,和 cgroups 联系紧密。
如果 Docker 的 cgroup driver 是 cgroupfs,就会存在两个控制管理器,对于该服务器上启动的容器使用的是 cgroupfs,而对于其他 systemd 管理的进程使用的是 systemd,这样在服务器资源负载高的情况下可能会变的不稳定。