docker 学习路线
参考资料
- 知乎 docker 的学习路线
- Docker — 从入门到实践
- Docker 核心技术与实现原理
- Docker 入门
- 《Kubernetes in Action》,想要学习 Kubernetes 的读者必定不要错过。
- 编程能力影响最大的两本书就是:
- 《计算机程序的构造和解释》(Structure and Interpertation of Computer Programming,SICP)
- 《计算机程序的概念、技术和模型》(Concepts, Techniques, and Models of Computer Programming,CTMCP)
理解 docker 的核心技术(core tech)
- docker 的核心技术有 namespace, control groups, union filesystem
Namespaces
- 命名空间 (namespaces) 是 Linux 为咱们提供的用于分离进程树、网络接口、挂载点以及进程间通讯等资源的方法。
- Docker 其实就经过 Linux 的 Namespaces 对不一样的容器实现了隔离。
- Linux 的命名空间机制提供了如下七种不一样的命名空间,包括 CLONE_NEWCGROUP、CLONE_NEWIPC、CLONE_NEWNET、CLONE_NEWNS、CLONE_NEWPID、CLONE_NEWUSER 和 CLONE_NEWUTS,经过这七个选项咱们能在建立新的进程时设置新进程应该在哪些资源上与宿主机器进行隔离。
- Docker 经过命名空间成功完成了与宿主机进程和网络的隔离。
进程
- 一个是 pid 为 1 的 /sbin/init 进程
- 负责执行内核的一部分初始化工做和系统配置,也会建立一些相似 getty 的注册进程。
- 另外一个是 pid 为 2 的 kthreadd 进程
- 这两个进程都是被 Linux 中的上帝进程 idle 建立出来的。
- Docker 容器内部的任意进程都对宿主机器的进程一无所知。
- 在 setNamespaces 方法中不只会设置进程相关的命名空间,还会设置与用户、网络、IPC 以及 UTS 相关的命名空间。
网络
- Docker 为咱们提供了四种不一样的网络模式,Host、Container、None 和 Bridge 模式。
- Docker 默认的网络设置模式:网桥模式。
- 除了分配隔离的网络命名空间以外,Docker 还会为全部的容器设置 IP 地址。
- 当 Docker 服务器在主机上启动以后会建立新的虚拟网桥 docker0,随后在该主机上启动的所有服务在默认状况下都与该网桥相连。
- 在默认状况下,每个容器在建立时都会建立一对虚拟网卡,两个虚拟网卡组成了数据的通道,其中一个会放在建立的容器中,会加入到名为 docker0 网桥中。
- libnetwork:
- 提供了一个链接不一样容器的实现,同时也可以为应用给出一个可以提供一致的编程接口和网络层抽象的容器网络模型。
挂载点
- 新的进程中建立隔离的挂载点命名空间须要在 clone 函数中传入 CLONE_NEWNS,这样子进程就能获得父进程挂载点的拷贝,若是不传入这个参数子进程对文件系统的读写都会同步回父进程以及整个主机的文件系统。
- 若是一个容器须要启动,那么它必定须要提供一个根文件系统(rootfs),容器须要使用这个文件系统来建立一个新的进程,全部二进制的执行都必须在这个根文件系统中。
- 为了保证当前的容器进程没有办法访问宿主机器上其余目录,咱们在这里还须要经过 libcontainer 提供的 pivot_root 或者 chroot 函数改变进程可以访问文件目录的根节点。
- chroot 的使用可以改变当前的系统根目录结构,经过改变当前系统的根目录,咱们可以限制用户的权利,在新的根目录下并不可以访问旧系统根目录的结构个文件,也就创建了一个与原系统彻底隔离的目录结构。
CGroups
- Control Groups(简称 CGroups)就是可以隔离宿主机器上的物理资源,例如 CPU、内存、磁盘 I/O 和网络带宽。
- 每个 CGroup 都是一组被相同的标准和参数限制的进程,不一样的 CGroup 之间是有层级关系的,也就是说它们之间能够从父类继承一些用于限制资源使用的标准和参数。
- 当咱们使用 Docker 关闭掉正在运行的容器时,Docker 的子控制组对应的文件夹也会被 Docker 进程移除,Docker 在使用 CGroup 时其实也只是作了一些建立文件夹改变文件内容的文件操做,不过 CGroup 的使用也确实解决了咱们限制子容器资源占用的问题,系统管理员可以为多个容器合理的分配资源而且不会出现多个容器互相抢占资源的问题。
- 每个 CGroup 下面都有一个 tasks 文件,其中存储着属于当前控制组的全部进程的 pid,做为负责 cpu 的子系统,cpu.cfs_quota_us 文件中的内容可以对 CPU 的使用做出限制。
UnionFS
- Linux 的命名空间和控制组分别解决了不一样资源隔离的问题,前者解决了进程、网络以及文件系统的隔离,后者实现了 CPU、内存等资源的隔离,可是在 Docker 中还有另外一个很是重要的问题须要解决 - 也就是镜像。
- 使用 docker run 很是轻松地从远程下载 Docker 的镜像并在本地运行。
- Docker 镜像其实本质就是一个压缩包,咱们可使用下面的命令将一个 Docker 镜像中的文件导出, docker export $(docker create busybox) | tar -C rootfs -xvf -
- Docker 中的每个镜像都是由一系列只读的层组成的,Dockerfile 中的每个命令都会在已有的只读层上建立一个新的层, 当镜像被 docker run 命令建立时就会在镜像的最上层添加一个可写的层,也就是容器层,全部对于运行时容器的修改其实都是对这个容器读写层的修改。
- 容器和镜像的区别就在于,全部的镜像都是只读的,而每个容器其实等于镜像加上一个可读写的层,也就是同一个镜像能够对应多个容器。
- AUFS 做为联合文件系统,它可以将不一样文件夹中的层联合(Union)到了同一个文件夹中,这些文件夹在 AUFS 中称做分支,整个『联合』的过程被称为联合挂载(Union Mount)。
- 每个镜像层或者容器层都是 /var/lib/docker/ 目录下的一个子文件夹;在 Docker 中,全部镜像层和容器层的内容都存储在 /var/lib/docker/aufs/diff/ 目录中。
- 而 /var/lib/docker/aufs/layers/ 中存储着镜像层的元数据,每个文件都保存着镜像层的元数据,最后的 /var/lib/docker/aufs/mnt/ 包含镜像或者容器层的挂载点,最终会被 Docker 经过联合的方式进行组装。
- Docker 还支持了不一样的存储驱动,包括 aufs、devicemapper、overlay二、zfs 和 vfs 等等,在最新的 Docker 中,overlay2 取代了 aufs 成为了推荐的存储驱动,可是在没有 overlay2 驱动的机器上仍然会使用 aufs 做为 Docker 的默认驱动。
- docker info | grep Storage 查看存储驱动
- Linux 命名空间、控制组和 UnionFS 三大技术支撑了目前 Docker 的实现,也是 Docker 可以出现的最重要缘由。
docker 基本组件
基本组件(Docker daemon, Docker client, registry镜像库, image镜像,container容器)nginx
- 容器 = 镜像 + 读写层
- 一个仓库会包含同一个软件不一样版本的镜像,而标签就经常使用于对应该软件的各个版本。
- Docker daemon 是服务器组件,以 Linux 后台服务的方式运行,是 Docker 最核心的后台进程,咱们也把它称为守护进程。它负责响应来自 Docker Client 的请求,而后将这些请求翻译成系统调用完成容器管理操做。该进程会在后台启动一个 API Server ,负责接收由 Docker Client 发送的请求,接收到的请求将经过Docker daemon 内部的一个路由分发调度,由具体的函数来执行请求。
- Docker Client ,也称 Docker 客户端。它其实就是 Docker 提供命令行界面 (CLI) 工具,是许多 Docker 用户与 Docker 进行交互的主要方式。
docker 实践
- 编写 Dockerfile 文件,设定 docker 编译规则
- docker build -t jianglong/nginx_web:v1 . 编译时设置仓库名,镜像名和版本号
- 构建完成以后,使用 docker images 命令查看全部镜像
- docker run --name nginx_web -d -p 8080:80 jianglong/nginx_web:v1 启动容器