前些日子帮朋友们安装wordpress配置环境时,算是被着实弄着急了一把。因为某人的带动,突然一大堆人想要搭建自己的博客。配环境时,一个两个我还能应付过来。这人一多了,我这也弄得有点乱了。寻找一种能批量操作环境配置的方法也就成了我的目标了。
docker也是这时开始了解的。以前也听说过docker,但由于总感觉是种“高大上”的应用,没有去过多深入了解。其实稍微学习一下,就会发现和git类似,看起来复杂,其实学起来很容易,也很能提高自己的效率。

本指南食用建议

这里牧云将自己学习的心得做出一个系列教程来,一方面为刚学习docker的朋友们提供一点帮助,一方面也是为自己做好笔记。由于是面向新手的教程,牧云尽量写得通俗易懂。有一些新手朋友可能无法理解的知识,文章通过字体(标题)的颜色来表达你需要对其的掌握程度:

  • 应该是紫色的字体:后备知识,解释后面之后教程的一些行为的原理方法。大家第一次看时可以跳过,后面遇到相关的知识时再回来看,可能就会豁然开朗了
  • 橙色字体:扩展知识,不掌握对应用影响不大,但是明白以后会更深刻的理解docker。

何为Docker?

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

简而言之,Docker 将应用程序与该程序的依赖环境,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题,通过Docker将各种应用打包成一个组合包,快速部署。

Docker 的接口相当简单,用户也可以方便地创建和使用容器,把自己的应用放入容器。

这也是docker的核心理念“Build Ship and Run Any App,Anywhere(一次封装,处处运行)”

如果实在对docker理解困难的话可以通过windows之前广泛运用的ghost系统来理解

docker-ghost

但请注意:Docker 不是虚拟机

关于虚拟化技术的科普,牧云在挑选合适的VPS主机有所涉及,感兴趣的朋友可以去阅读一二。

何处用Docker?

由于docker拥有通过镜像可以方便快捷的部署并管理容器的特性。使得其能在如下场景中发挥很大的作用。

  • 提供一次性的环境。比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。
  • 提供弹性的云服务。因为 Docker 容器可以随开随关,很适合动态扩容和缩容。
  • 快速部署应用。通过镜像部署容器,快速将应用部署在各个需要的主机上。
  • 管理编译环境。在需要各种不同编译环境中,可以通过部署各类容器,实现管理。
    ![](https://img.006900.xyz/imgs/Docker-Menu-1/docker_usage.png)

何解Docker?

docker 架构

Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。其组件构成如下

  • 后台守护进程(daemon process)
  • 一个REST API指定特定的接口
  • 命令行端口(client)
![](https://img.006900.xyz/imgs/Docker-Menu-1/construction.png) CLI(client)使用Docker的REST API来和Docker的守护进程(daemon)交互,告诉守护进程创建和管理Docker镜像、容器、网络、数据卷等。

下面这张图告诉我们docker的运行架构

核心概念

Docker在运行中有几个重要的概念,我们在这里给大家来分别解释一下。其中镜像容器的关系是需要大家多理解一下的

  • 主机(host):亦可称为“宿主”,是一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。简单理解就是运行docker的机器。
  • 镜像(Image):Docker 把应用程序及其依赖,打包在 image 文件里面。可以理解为容器的模板,文件是只读的。
  • 容器(container):Docker通过images文件生成的实例,用来运行一组或多组应用。各个不同容器之间相互隔离,互不可见。(但可以进行通讯,后面的教程会提及)
  • 仓库(Registry):Docker 仓库用来保存镜像,并供用户远程下载使用。注册服务器(reg)是存放仓库的地方,注册服务器上有多个仓库,每个仓库中放一类镜像,包括多个镜像文件,通过不同的标签(tag)区分。

镜像和容器

镜像和容器这两个概念看起来是很容易理解的,但在使用docker的过程中,如果对这两个概念的理解不到位,则是很容易在使用时发生错误的。接下来我们更为细致的讲解一下这两个概念。

镜像

之前说过,镜像即是应用程序及其依赖打包而成的imgae文件。而image文件则是一堆只读层(read-only layer)的统一视角。我们可以通过下面这张图来理解一下

我们可以在左边看到很多的读取层,这些层是Docker内部的实现细节,并且能够在主机上访问的到。并且,这些层是只读的,但是在构建image文件时,每对容器进行一次修改,就会在该层上再新建一层并记录修改。在右图中,最顶层通过统一文件系统(union file system)读取,以此整合成单一文件视角并呈现出一个只读文件,以此来隐藏了多层的存在。

我们可以在主机(并非容器)上的查看这个“多层”视角,它存在于/var/lib/docker下的aufs目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# sudo tree -L 1 /var/lib/docker/
/var/lib/docker/
├── aufs
├── containers
├── graph
├── init
├── linkgraph.db
├── repositories-aufs
├── tmp
├── trust
└── volumes

7 directories, 2 files

容器

在联合视角中,容器几乎和镜像一模一样,只是最上层是可读可写层。


需要注意的是,其实容器仅仅被定义为这个图像最顶层。

也就是说,当我们运行一个容器的时候,就是将镜像最上层覆盖上一个读写层,并且无论对该容器进行如何的操作都将只作用于镜像的读写层。
而当我们使用commit命令提交容器成为镜像时,就是将将容器的读写层变为仅读层。

后记

基础概念我们就介绍到这了,后续我们会开始为大家讲解docker的使用方法以及docker使用实例的。

参考资料:
Visualizing Docker Containers and Images
Docker 基础入门+实例