转载

Docker浅析,或者如何从Vagrant转向Docker

Docker是新一代的虚拟化技术,如今大概有三年的历史了。较之以前,它能让构建技术栈复杂的软件更加容易,且隔离性更好。我说的以前,指的是Vagrant,Chef,Puppet等。这些技术的套路都是创建一个基础镜像(包含操作系统和一些基本的软件),并且使用脚本来安装需要的软件或者配置。最后得到一个完整镜像,然后可以轻易地生成快照并且稳定地用于部署了,或者我当时是这么认为的。

背景故事

我们在工作中一直使用 PuPHPet ( 译者注:一个可以配置虚拟机的GUI,可以生成Vagrant的Web开发环境,主要使用Puppet来作为配置后端 ),到现在至少已经有一年了。PuPHPet用的是YAML格式的配置文件,有很多中间件脚本来构建虚机(machine)。对虚机做改动需要更改YAML配置文件,然后重新执行 vagrant provision 命令。最初我们感觉像找到了天堂,因为没有它我们需要编写很多些糟心的bash/puppet脚本。而当初它唯一的不足之处只是项目需要提交巨量的文件;不过这是一桩挺公平的买卖。

随着时间推移,PuPHPet自己也在快速的更新。YAML配置文件的格式也变了,最初使用的不同软件包组合也不再支持了,也没有谁给点合理的理由,除了项目想向前推进,只想关注最新的软件包。最无法接受的下边的子系统,Puppet和Ruby的依赖也在不断的变化。这意味着新来的一个开发者,想要构建一个月前还正常的虚机的时候,几乎总是崩溃的。

因此,在一年的时间里,我们不得不很多次完整地对基础配置进行完全重建,而每一次总会给团队带来很大的波动。最后,操作系统( CentOS类的Linux )和PHP( 我们依赖版本是PHP5.4 )的结合不工作了,因为默认的(PHP)软件仓库已经不在了。

够了就是够了,我们需要一些更加稳定的东西。

Docker介绍

Docker文档太烂了,这是我见过的最烂的文档之一。对我来说,看了之后我更加糊涂。它编写的时候是假定你已经非常熟悉基于容器的基础设施,并且什么也都不解释一下,或者没有任何你想要寻求的东西。

我想重点介绍一些“明摆着的”的事情,一旦解释清了就很容易理解,但是如果你没有花时间反复尝试却难以理解。希望这能帮助你更顺利的向Docker迁移或者理解Docker。

1. 容器(Container)

Docker使用一种与众不同的虚拟化技术,被称之为 容器 。一个容器可以被想象成一个完全自包含的机器(machine),为了各种想法或者目标它有自己的操作系统,自己的文件系统,或者任何其他你期待在一个虚拟机器上拥有的东西。但是有一点很重要的是,容器只运行一个程序( 注:一个容器实际上可以运行多个进程。然而,正常情况下,不会这么做,除非有特别的原因。在几乎所有的场景中,最好在一个容器中只运行一个进程或者服务。 )。例如你可能在一个容器中运行一个MySQL服务,然后在另外一个的容器中运行Redis服务。

即使每个容器的运行基于一个自包含的操作系统,但是他并不像一个专用虚拟操作系统那样需要那么多资源。很多容器可以和主机分享物理资源(像CPU和内存)。

参考链接

  • Docker的命令行使用文档

2. 镜像(Image)

镜像是文件系统的一个快照,然而它们总是基于另外一个镜像。例如,如果我们拿到了一个容器的镜像,它的大小是200MB,然后安装了10MB大小的软件,并生成了另外一个镜像,这个镜像的大小只有10MB,因为它只包含在上一个镜像的基础上所做的更改。

镜像不包含内核,所以通常能看到一些只有几兆大小的镜像。

镜像会被缓存,这可以让容器重新构建非常非常的快。

参考链接

  • 探索官方的仓库

3. 无状态(Stateless)

每个容器都可能有来自主机挂载到容器里的目录。例如你如果你运行了一个Apache的Web服务器容器,你可能不想将要服务的源文件都塞到容器里面去。相反,你会将一个主机上的目录(其中包含web服务器要服务的文件)挂载到容器中的一个目录,比如:

/Users/elliot/Development/mywebsite -> /var/www/html

这样容器(和镜像)就是无状态的了。容器重启或者镜像删除都不会影响应用。这同时让镜像体积更小,重用性更高。另外一个好处是很多容器能共享一个挂载的目录。例如,如果你有多个的web服务器对外提供相同的文件。

4. Dockerfile

Dockerfile 是一个纯文本文件,通常位于项目根目录下面。其中包含构建镜像的步骤。这与通常用来安装软件或者设置环境变量的bash脚本类似。一个Dockerfile可能像下面这样:

FROM php:7.0-apache
COPY config/php.ini /usr/local/etc/php/
ENV APP_ENV dev

每一行都是一个命令( command )。第一行总是一个 FROM 命令,来指定基于什么基础镜像来进行构建。每一步都会创建一个新的镜像,但是每一个镜像只会包含基于上一个快照的更改(上一个命令)。

如果容器是没有状态的,你就能更改Dockerfiler然后快速并且容易地重新构建容器。

参考链接

  • Dockerfile参考文档
  • Dockerfile编写的最佳实践

5. 多个容器

一般情况下你的应用可能不止包含一个容器,你可能需要多个容器来提供其他服务,如数据库、web service、后台任务等。这时候我们可以使用 docker-compose 命令。

这里是一个 docker-compose.yml (通常位于项目的根目录下面)的例子,用来构建一个Wordpress的应用。

version: '2'
services:
db:
image: mysql:5.7
volumes:
- "./.data/db:/var/lib/mysql"
restart: always
environment:
MYSQL_ROOT_PASSWORD: wordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress

wordpress:
depends_on:
- db
image: wordpress:latest
links:
- db
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_PASSWORD: wordpress

运行 docker-compose up 会创建两个容器,一个叫 db ,一个叫 wordpress 。他们将会位于同一个虚拟网络之下。

相关链接:

  • Docker Compose
  • Compose file参考
  • Compose命令行参考

6. 容器网络

docker-compose 构建的容器会处于同一个虚拟网络中。然而你也可以配置各种你想要的样子,但是有一些需要注意的地方:

  1. 容器(如果允许的话)会使用容器的名字作为主机名(hostname)。例如,如果 wordpress 容器想要连接到 db 容器,它会使用db作为主机名。
  2. 默认情况下,容器是 不能 连接到其他容器的,除非明确这样配置。要让 wordpress 服务能访问 db 服务,需要明确地在 links 属性中指定。
  3. 默认情况下,宿主操作系统不能访问容器中的端口。因为 wordpress 是一个web服务器,我们需要将容器内部的 80 端口映射到宿主机的 8080 端口。这意味着我们可以在宿主机的浏览器中通过 localhost:8080 访问到这个Wordpress应用。

参考链接:

  • 理解的Docker容器的网络

总结

这篇文章非常简单地介绍了Docker。我希望能在以后的文章中就单独的主题做更加详细的介绍,所以敬请期待。

这里有一篇深度介绍 容器和镜像 的文档。

(原文: Docker: Explained Simply Or, How to Move Away From Vagrant , 翻译:钟最龙)

原文  http://dockone.io/article/1612
正文到此结束
Loading...