Docker入门概念
什么是Docker?
Docker项目的目标是实现轻量级的操作系统虚拟化解决方案;
Docker的基础是Linux容器(LXC)等技术
Docker与传统VM的区别
Docker基于系统层面抽象而来:直接复用本地的操作系统;而传统VM基于硬件层面抽象实现;
为什么要使用Docker
Docker的容器启动可以在秒级实现;Docker对系统资源的利用率很高;
传统VM运行10个应用要启动10个VM,而Docker只需要启动10个隔离的应用即可;
Docker的优势:
更快速的交付和部署:大量地节约开发、测试、部署的时间;
更高效的虚拟化,不需要hypervisor支持,是内核级的虚拟化:因此可以实现更高的性能和效率;
更轻松的迁移和扩展,更简单的管理
Docker基本概念
镜像(Image)
容器(Container)
仓库(Repository)
这三个概念,贯穿了Docker的整个声明周期;
更多的时候,需要让 Docker 容器在后台以守护态(Daemonized)形式运行。此时,可以通过添加 -d 参
数来实现。
精彩篇章:
12.安全:
内核能力机制
能力机制(Capability)是 Linux 内核一个强大的特性,可以提供细粒度的权限访问控制。 Linux 内核自
2.2 版本起就支持能力机制,它将权限划分为更加细粒度的操作能力,既可以作用在进程上,也可以作用在
文件上。
例如,一个 Web 服务进程只需要绑定一个低于 1024 的端口的权限,并不需要 root 权限。那么它只需要被
授权 net_bind_service 能力即可。此外,还有很多其他的类似能力来避免进程获取 root 权限。
大部分情况下,容器并不需要“真正的” root 权限,容器只需要少数的能力即可。
现有的安全机制来增强使用 Docker 的安全性,例如 TOMOYO,
AppArmor, SELinux, GRSEC 等。
Docker 当前默认只启用了能力机制
Dockerfile
使用 Dockerfile 可以允许用户创建自定义的镜像。
Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。
一般的,Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
底层实现
Docker 底层的核心技术包括 Linux 上的名字空间(Namespaces)、控制组(Control groups)、Union 文
件系统(Union file systems)和容器格式(Container format)。
我们知道,传统的虚拟机通过在宿主主机中运行 hypervisor 来模拟一整套完整的硬件环境提供给虚拟机的
操作系统。虚拟机系统看到的环境是可限制的,也是彼此隔离的。 这种直接的做法实现了对资源最完整的
封装,但很多时候往往意味着系统资源的浪费。 例如,以宿主机和虚拟机系统都为 Linux 系统为例,虚拟
机中运行的应用其实可以利用宿主机系统中的运行环境。
我们知道,在操作系统中,包括内核、文件系统、网络、PID、UID、IPC、内存、硬盘、CPU 等等,所有
的资源都是应用进程直接共享的。 要想实现虚拟化,除了要实现对内存、CPU、网络IO、硬盘IO、存储空
间等的限制外,还要实现文件系统、网络、PID、UID、IPC等等的相互隔离。 前者相对容易实现一些,后
者则需要宿主机系统的深入支持。
随着 Linux 系统对于名字空间功能的完善实现,程序员已经可以实现上面的所有需求,让某些进程在彼此
隔离的名字空间中运行。大家虽然都共用一个内核和某些运行时环境(例如一些系统命令和系统库),但
是彼此却看不到,都以为系统中只有自己的存在。这种机制就是容器(Container),利用名字空间来做权
限的隔离控制,利用 cgroups 来做资源分配。
名字空间
名字空间是 Linux 内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在
独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。
pid 名字空间
不同用户的进程就是通过 pid 名字空间隔离开的,且不同名字空间中可以有相同 pid。所有的 LXC 进程在
Docker 中的父进程为Docker进程,每个 LXC 进程具有不同的名字空间。同时由于允许嵌套,因此可以很
方便的实现嵌套的 Docker 容器。
net 名字空间
有了 pid 名字空间, 每个名字空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是
通过 net 名字空间实现的, 每个 net 名字空间有独立的 网络设备, IP 地址, 路由表, /proc/net 目录。这样每
个容器的网络就能隔离开来。Docker 默认采用 veth 的方式,将容器中的虚拟网卡同 host 上的一 个Docker
网桥 docker0 连接在一起。
ipc 名字空间
容器中进程交互还是采用了 Linux 常见的进程间交互方法(interprocess communication - IPC), 包括信号
量、消息队列和共享内存等。然而同 VM 不同的是,容器的进程间交互实际上还是 host 上具有相同 pid 名
字空间中的进程间交互,因此需要在 IPC 资源申请时加入名字空间信息,每个 IPC 资源有一个唯一的 32
位 id。
mnt 名字空间
类似 chroot,将一个进程放到一个特定的目录执行。mnt 名字空间允许不同名字空间的进程看到的文件结
构不同,这样每个名字空间 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个名字空间中的
容器在 /proc/mounts 的信息只包含所在名字空间的 mount point。
uts 名字空间
UTS("UNIX Time-sharing System") 名字空间允许每个容器拥有独立的 hostname 和 domain name, 使其在
网络上可以被视作一个独立的节点而非 主机上的一个进程。
user 名字空间
每个容器可以有不同的用户和组 id, 也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。
控制组(cgroups)
控制组(cgroups)是 Linux 内核的一个特性,主要用来对共享资源进行隔离、限制、审计等。只有能控制
分配到容器的资源,才能避免当多个容器同时运行时的对系统资源的竞争。
控制组技术最早是由 Google 的程序员 2006 年起提出,Linux 内核自 2.6.24 开始支持。
控制组可以提供对容器的内存、CPU、磁盘 IO 等资源的限制和审计管理。
联合文件系统
联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一
次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a
single virtual filesystem)。
联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以
制作各种具体的应用镜像。
另外,不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存
储的效率。
Docker 中使用的 AUFS(AnotherUnionFS)就是一种联合文件系统。 AUFS 支持为每一个成员目录(类
似 Git 的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限, 同时 AUFS 里有
一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。
Docker 目前支持的联合文件系统种类包括 AUFS, btrfs, vfs 和 DeviceMapper。
容器格式
最初,Docker 采用了 LXC 中的容器格式。自 1.20 版本开始,Docker 也开始支持新的 libcontainer 格式,
并作为默认选项。
对更多容器格式的支持,还在进一步的发展中。
Docker 网络实现
Docker 的网络实现其实就是利用了 Linux 上的网络名字空间和虚拟网络设备(特别是 veth pair)。建议先
熟悉了解这两部分的基本概念再阅读本章。
首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包;此外,如果
不同子网之间要进行通信,需要路由机制。
Docker 中的网络接口默认都是虚拟的接口。虚拟接口的优势之一是转发效率较高。 Linux 通过在内核中进
行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据包被直接复制到接收接口的接
收缓存中。对于本地系统和容器内系统看来就像是一个正常的以太网卡,只是它不需要真正同外部网络设
备通信,速度要快很多。
Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通
(这样的一对接口叫做 veth pair )。
Docker 创建一个容器的时候,会执行如下操作:
创建一对虚拟接口,分别放到本地主机和新容器中;
本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 veth65f9;
容器一端放到新容器中,并修改名字作为 eth0,这个接口只在容器的名字空间可见;
从网桥可用地址段中获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 veth65f9。
完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。
Docker相关周边
Docker Compose 是 Docker 官方编排(Orchestration)项目之一,负责快速在集群中部署分布式应用。
本章将介绍 Compose 项目情况以及安装和使用。
Docker Machine 是 Docker 官方编排(Orchestration)项目之一,负责在多种平台上快速安装 Docker 环
境。
Docker Swarm 是 Docker 官方编排(Orchestration)项目之一,负责对 Docker 集群进行管理。
etcd 是 CoreOS 团队发起的一个管理配置信息和服务发现(service discovery)的项目
Fig:在你的应用里面添加一个 fig.yml 文件,并指定一些简单的内容,执行 fig up 它就能帮你快速建立起
一个容器。目前已经正式更名为 Compose。
CoreOS的设计是为你提供能够像谷歌一样的大型互联网公司一样的基础设施管理能力来动态扩展和管理的
计算能力。
CoreOS的安装文件和运行依赖非常小,它提供了精简的Linux系统。它使用Linux容器在更高的抽象层来管理
你的服务,而不是通过常规的YUM和APT来安装包。
同时,CoreOS几乎可以运行在任何平台:Vagrant, Amazon EC2, QEMU/KVM, VMware 和 OpenStack 等
等,甚至你所使用的硬件环境。
Kubernetes 是 Google 团队发起并维护的基于Docker的开源容器集群管理系统,它不仅支持常见的云平
台,而且支持内部数据中心。
建于Docker之上的Kubernetes可以构建一个容器的调度服务,其目的是让用户透过Kubernetes集群来进行
云端容器集群的管理,而无需用户进行复杂的设置工作。系统会自动选取合适的工作节点来执行具体的容
器集群调度处理工作。其核心概念是Container Pod(容器仓)。一个Pod是有一组工作于同一物理工作节
点的容器构成的。这些组容器拥有相同的网络命名空间/IP以及存储配额,可以根据实际情况对每一个Pod
进行端口映射。此外,Kubernetes工作节点会由主系统进行管理,节点包含了能够运行Docker容器所用到
的服务。
常见仓库介绍
本章将介绍常见的一些仓库和镜像的功能,使用方法和生成它们的 Dockerfile 等。包括 Ubuntu、
CentOS、MySQL、MongoDB、Redis、Nginx、Wordpress、Node.js 等。