天天看点

Docker 容器概念

<b>不玩虚的, 当然更畅快</b>

docker 与虚拟机(vm)对比:

Docker 容器概念

<a></a>

虚拟机运行在虚拟硬件上, 应用运行在虚拟机内核上。而 docker daemon 是宿主机上的一个进程, 应用只是 docker daemon 的一个子进程, 换句话说, 应用直接运行在宿主机内核上。

虚拟机需要特殊硬件虚拟化技术支持, 因而只能运行在物理机上。docker 没有硬件虚拟化, 因而可以运行在物理机、虚拟机, 甚至 docker 容器内(嵌套运行)。

因为没有硬件虚拟化及多运行一个 linux 内核的开销, 应用运行在 docker 上比虚拟机上更轻、更快。

说到隔离, docker 容器的文件系统在哪里呢? 答案就是镜像。

镜像描述了 docker 容器运行的初始文件系统, 包含运行应用所需的所有依赖。即可以是一个完整的操作系统, 也可以仅包含应用所需的最小 bin/lib 文件集合。

一个问题: 假设一个 docker 容器文件系统大小为 10gib, 创建 10 个容器需要多少磁盘空间?

100 gib?错,还是只要 10 gib!因为 docker 镜像和容器采用分层文件系统结构, 每个容器包含一层薄薄的可写层, 只读部分是共享的。

Docker 容器概念

镜像是只读的, 创建容器时只是在镜像上面新建一个可写层, 不需要复制整个文件系统, 因而可以实现毫秒级创建。

镜像存储在镜像 hub。每个镜像有一个 tag, 如 <code>registry.hub.docker.com/library/ubuntu:14.04</code>。镜像完整 tag 不仅包含镜像名字, 还指明了镜像从哪里来, 要到哪里去, 就像一个 url。没错, <code>registry.hub.docker.com</code> 就是官方 docker 镜像 hub 的地址。使用官方 library 镜像时, 可省略前缀, 如以上镜像 tag 可简写为 <code>ubuntu:14.04</code>。

so, 创建一个 docker 容器的命令行如下:

这只是创建了容器, 还没有运行, 要运行容器, 执行:

通常我们把这两条命令合并成一条, 即 <code>docker run</code>:

在宿主机上看一下我们刚刚运行的 <code>bash</code> 命令的进程树:

没错, 它只是 docker daemon 的一个子进程.

attach 到容器内的应用, 本例中即为 bash 命令行:

<code>ps -ef</code> 看一下:

加上 <code>ps</code> 自己, 容器中只有两个进程。 <code>bash</code> 在容器内 pid 为 1, 即是容器主进程。主进程退出后, 容器即自动退出。还是那句话, 容器为运行应用而生, 应用都退出了, 容器留着还有什么用。

手动停止容器:

删除容器:

注意: 删除容器后在镜像上创建的可写层文件系统也将被删除, 所以日志、配置、数据等需要持久保存的文件需要挂接到外部储存。

俗话说前人栽树, 后人乘凉, 我们通常是基于一个已有的镜像创建应用镜像。为了演示镜像有多轻,我们可以从 0 开始创建一个镜像。

创建一个文件夹 <code>hello-lark</code>, 进入文件夹, 添加一个 <code>dockerfile</code> 内容如下:

<code>dockerfile</code> 描述如何创建镜像:

<code>from scratch</code> 表示从 0 开始, 即从一个空白文件系统开始创建镜像。

<code>copy dockerfile hello.c hello /</code> 表示将本地 <code>dockerfile</code>, <code>hello.c</code>, <code>hello</code> 3 个文件复制到镜像内根目录下。

<code>hello.c</code> 和 <code>hello</code> 是我们的应用源码及编译后的二进制文件。

添加 <code>hello.c</code> 文件内容如下:

静态编译之:

执行 <code>docker build</code> 创建镜像:

镜像在本地仓库打包和存储, 不能直接看到实体文件。但是可以导出为一个 tar 包:

看看有多大:

仅有 870k, 差不多就是 <code>hello</code> 这个二进制文件的大小。

这个镜像能跑吗?我们马上运行看看:

可看到, 这条命令一共经历了容器创建、运行、停止、销毁 4 个过程,共耗时不到 0.5 秒。<code>--rm</code> 表示容器结束后自动删除容器。

如果只是创建:

不到 0.1 秒。毫秒级创建绝非虚言。

当然, 只是 hello world 并没有什么用, 我们打一个 busybox 进去, 镜像大小只有 2mb, 然而已经具备一个基本的 linux shell 环境.

简单说: 标准化交付,微服务编排,提升资源利用率。

校准化交付

docker 将应用及其所有依赖打包到镜像内, 包括二进制文件(包括底层基础库), 静态配置文件, 环境变量等。剥离了应用对操作系统和环境的依赖, 松耦合 。只需要拉取镜像, 启动容器即可完成应用部署, 方便 。毫秒级创建销毁容器,从而可以实现快速部署、快速迁移、快速扩容缩容,一键快速回滚 (只依赖应用启动时间)。docker 镜像制定了应用交付标准, 开发人员对应用及其运行环境完全可控,并 有效避免各种环境问题踩坑。

微服务编排

单机部署多应用时,应用之间完全解耦,可以任意部署编排, 完美支持微服务编排的需求。多个 c 应用混布时, docker 化实现 c 依赖隔离, 避免依赖冲突。

提升资源利用率

docker 是轻量级的解决方案, 不做虚拟化, 不运行多余的 kernel 和 init 进程, 能有效提升资源利用率。