如何在Docker容器之间拷贝数据

amwtke 发表了文章 • 0 个评论 • 17168 次浏览 • 2014-12-17 21:59 • 来自相关话题

【编者的话】在容器之间拷贝数据是Docker一个重要而且基本的功能。拷贝数据到其他容器是一个经常使用到的场景,如当服务器遇到不可预见的“灾难”(注:断电,宕机)时,起到备份数据的作用。本文作者详细介绍了操作步骤。 如何在Docker容 ...查看全部
【编者的话】在容器之间拷贝数据是Docker一个重要而且基本的功能。拷贝数据到其他容器是一个经常使用到的场景,如当服务器遇到不可预见的“灾难”(注:断电,宕机)时,起到备份数据的作用。本文作者详细介绍了操作步骤。

如何在Docker容器之间拷贝数据

Docker容器可以类比成一个目录,它可以将一个应用程序运行时所依赖的所有环境(注:此应用依赖的其他的服务或程序等)打包在一起运行;同时可以随意的对它进行“启动”、“停止”、“移动”或者“删除”等操作。Docker容器在Linux的命名空间(Namespace)机制下被激活,这样就可以使得运行在同一服务器上的不同Docker容器能在网络(Networking)与存储(storage)层面上被“隔离”(isolation)的运行。每个Docker容器都是在一个Docker镜像(image)的基础上创建而来;而一个Docker镜像可以支持创建、运行多个Docker容器,这主要取决于服务器的硬件性能。所以,Docker容器是Docker运行时的表现形式。
#什么是Docker镜像?
Docker容器是基于一个Docker镜像创建的,而Docker镜像本身则可以通过Docker命令行工具或者Dockerfiles来生成。Docker镜像既可以包含操作系统基础设施(fundamentals)也可以包含一个预先搭建好的可以直接启动的应用程序栈。Docker镜像可以被看做是一个只读的模板,这个模板中包含了很多“层”;而任何基于这个Docker镜像的新增操作或者更新操作都会导致一个基于当前层的新的层被创建出来,这个新创建的层是直接叠加在当前层之上的而非覆盖整个Docker镜像(注:创建新层的过程就是创建新容器的过程)。这就是一个新的Docker容器是怎么被创建出来的。
#从一个容器拷贝数据到另一个容器:
在容器之间拷贝数据是Docker一个重要而且基本的功能。拷贝数据到其他容器的功能是一个真实的用户场景,如当服务器遇到不可预见的“灾难”(注:断电,宕机)时,起到备份数据的作用。
#使用容器的数据卷:
数据卷(data volume,注:位置在/var/lib/docker/volumes)是容器可以访问,但是位置不在root文件系统中的一个目录。为了能让容器之间可以共享数据,Docker让“卷”(volume)可以绕过Docker镜像的层叠机制。容器中所有对镜像的改变全部都直接存储。每个容器都有固定的运行目录在/var/lib/docker目录下;而每个容器卷的数据则默认单独存储在/var/lib/docker/volumes/目录底下。`docker run`命令的`-v`选项能够实现容器间数据卷中数据的互相拷贝。
#如何在容器之间拷贝数据的一个例子
在这个例子中,我们假设基于镜像mymod/dvc:v1创建并运行了两个容器:dvc1与dvc2,以下是启动这两个镜像的命令:
```
# docker run –d –name dvc1 mymod/dvc:v1
# docker run –d –name dvc2 mymod/dvc:v1
```
以下命令将创建并启动一个新的容器(也是基于mymod/dvc: v1镜像)但是挂载dvc1的数据卷,并使用cp命令拷贝容器dvc1中的数据到宿主机(host)上。
```
[root@host ~]# docker run –rm –v /var/tmp:/host:rw \ –volumes- from dvc1 cp –r/var/www/html/host/dvc1_files
```
[注:经过测试以上命令应该改为以下形式才能运行]
```
[root@host ~]# docker run –rm –v /var/tmp:/host:rw –volumes-from dvc1 mymod/dvc: v1 cp –r /var/www/html/host/dvc1_files
```
新建的容器以读-写权限挂载宿主机的/var/temp目录为/host目录,然后挂载所有dvc1的数据卷,包含dvc1中的/var/www/html目录,然后拷贝/var/www/html的文件目录到/host/dvc1_files下,対映宿主机/var/temp目录。

现在我们用以下命令拷贝dvc1容器的数据到其他的容器中:
```
[root@host ~]# docker run –rm –v /var/tmp:/host:ro –volumes-from dvc2 \ cp –a –T /host/dvc1_files /var/www/html
```
新建的容器将宿主机的/var/tmp目录以只读的形式映射到dvc2容器的/host目录中,同时加载dvc2容器的所有数据卷,然后将/host/dvc1_files(对应宿主机/var/tmp/dvc1_files)目录的结构拷贝到dvc2容器的/var/www/html目录下。

同样的目标可以在Dockerfile中使用ADD命令实现。ADD有两个参数一个是源容器一个是目的容器。ADD命令可以实现从源容器拷贝文件或者数据到目的容器的目标,而不用管各个容器的文件系统差异。
#结论:-
Docker肯定会提供更好的方式来“培养”容器化服务部署,以支持更广泛的部署平台;同时开发社区也期望Docker构建服务层级(service layer)。而Docker的做法是:开发容器核心容量,开发跨容器服务管理与通信功能。我们在这篇文章中所阐述的是数据可以在容器间被复制与冗余,这可以用来应付各种数据的损毁与恢复。Docker还提供了使用方便的容器间差异分析功能,这可以让容器更好的支持排错(debugging)、快速共享部署环境以达到快速的部署的目标。Docker可以将容器部署环境从开发或者QA阶段直接提交到AWS部署环境。用户可以通过Docker的数据卷在容器间共享数据;可以将宿主机的目录直接挂载到容器中或者甚至可以从容器中导出数据存档,所以,Docker非常方便。

原文链接:http://devops.com/blogs/devops-toolbox/copying-data-one-docker-container-another/

在Docker中运行Node.js的Web应用

marshal 发表了文章 • 4 个评论 • 22219 次浏览 • 2014-12-17 15:39 • 来自相关话题

【编者的话】本文是十七蝉同学撰写的基础实战类博客,作者通过代码的形式Step by step介绍了如何在Docker中运行Node.js应用。初学的同学可以一读。 在Docker环境下搭建了Node.js的Web应用运行环境: ...查看全部
【编者的话】本文是十七蝉同学撰写的基础实战类博客,作者通过代码的形式Step by step介绍了如何在Docker中运行Node.js应用。初学的同学可以一读。

在Docker环境下搭建了Node.js的Web应用运行环境:
* Node.js
* MongoDB
* Redis
* winston和morgan,日志

以下介绍一下搭建环境的步骤和注意事项。
准备工作
需要安装Docker,我的环境是Ubuntu Serer 14.04虚拟机。如果直接用`apt-get install docker.io`无法获得比较新的Docker版本。我参照这里:Docker 1.2 on Ubuntu 14.04.1,安装了Docker 1.2版本。即使用Docker官方的第三方Ubuntu源。

加入Docker的GPG Key

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9

加入Docker的源:

sudo sh -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"

更新包列表:

sudo apt-get update

安装Docker

sudo apt-get install lxc-docker

重启系统:

sudo reboot

如果执行下面命令并看到类似的结果就说明安装成功了:

$ docker version
Client version: 1.2.0

最简单的通过Docker执行Node.js
执行一个简单的Node.js命令:

node --version

不是使用本地的Node.js,而是使用Docker,只需执行:

$ sudo docker run -it --rm node node --version
v0.10.33

对于第一次运行上面命令,会出现类似:

Unable to find image 'node' locally
Pulling repository node
63d7e1e1d897: Pulling dependent layers
511136ea3c5a: Download complete
36fd425d7d8a: Download complete
aaabd2b41e22: Download complete
f99c114b8ec1: Downloading [==>
...

Docker本地并没有node的镜像(image),需要到官网(https://hub.docker.com)上查询这个名字的镜像,并下载到本地。这个过程可能比较漫长,在我这里需要30分钟左右。总之,下载完镜像(700多MB)后,镜像会启动一个容器(container)。可以把镜像看做Java的类(class),容器看做对象(object)。

这个容器包含一个最小的可运行的轻量级的虚拟机,当然还有Node.js。

说下命令的参数:

```
docker run -it --rm node node --version
```

其中`--it`:

* `i`,容器的标准输入保持打开
* `t`,Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入

`--rm`,运行结束后删除容器。再后面就是我们要执行的命令。
将Web Application跑起来
首先,要准备一个简单的Web Application。我这里写好了一个简单的应用ProtoWebApp。拿到项目文件后,先用宿主的node安装:
```
$ sudo npm install
```
然后跑起来测试一下,看是否能在浏览器上访问。
下面,是用Docker里的Node.js跑这个Web Application了(在项目的根目录下):

sudo docker run --rm -it -p 3000:3000 --name ProtoWebApp -v "$(pwd)":/webapp -w /webapp node npm start

在这里:
* `-v`后`:`分割的路径,前者表示宿主的路径(在这里也就是expressjs项目的主目录),后者表示映射到Docker容器的路径。
* `-w`,表示将`-v`映射的`/webapp`目录设置为work directory,也就是运行node命令的目录。这个设置将覆盖`Dockfiie`中的设置:`/Data`。

如果需要让Docker容器跑在后台,可以加上`-d`:

sudo docker run --rm -itd -p 3000:3000 --name ProtoWebApp -v "$(pwd)":/webapp -w /webapp node npm start

另外,如想了解这个镜像都包含哪些内容,可以看这里:Dockerfile/Node.js
日志的处理
运维中需要记录几种日志:

* HTTP请求日志,为了以后分析访问量等数据时使用
* 应用日志,可能有错误或者其他调试信息,便于发现错误,排错

# HTTP请求日志
很多情况下未必用到这个,因为在Node.js的Web Appp前,可能还有Nginx,用后者做端口代理。目前的Expressjs,是4.x版本,使用的HTTP日志,是morgan。可以在`app.js`中看到:
```
var logger = require('morgan');
```
默认的日志是对接到标准输出上的。我们希望在生产环境(production)下和开发环境(development)情况下不一样:
* 生产环境(production):HTTP日志记录到文件
* 开发环境(development):打印到标准输出

这需要做两件事:
    []通过docker命令设置为`production`[/][]`app.js`在`production`情况下记录日志到文件中[/]

`docker run`命令中加入`production`变量设置:

sudo docker run --rm -it -p 3000:3000 --name ProtoWebApp -v "$(pwd)":/webapp -w /webapp -e NODE_ENV=production node npm start

即,`-e NODE_ENV=production`。
设置保存日志到文件。找到`app.js`的这行:
```
app.use(logger('dev'));
```
改为:

if (app.get('env') === 'development') {
app.use(logger('dev'));
}

if (app.get('env') === 'production') {
var fs = require('fs')
var accessLogStream = fs.createWriteStream(__dirname + '/access.log', {flags: 'a'})
app.use(logger('combined', {stream: accessLogStream}))
}

这样,当`development`模式打印到标准输出,`production`模式下输出到项目根目录下的`access.log`文件中。源代码见这里:https://github.com/MarshalW/ProtoWebApp/tree/m2
# 应用日志
这个日志是必须要有的,可帮助开发者发现和诊断问题。使用的是winston。需要将winston加入到package.json中:

"winston":""

然后引入库:
```
var winston = require('winston');
```
再设置文件路径(我这里是`app.log`):

if (app.get('env') === 'production') {
var accessLogStream = fs.createWriteStream(__dirname + '/access.log', {flags: 'a'});
app.use(logger('combined', {stream: accessLogStream}));

winston.add(winston.transports.File, { filename: 'app.log' });
}

Docker不需要设置什么,就可以在项目的根目录下看到`app.log`文件了,如果运行没有问题的话。
连接Redis
和Node.js镜像类似,可以通过如下命令将Redis跑起来:
```
$ sudo docker run -d --name redis -p 6379:6379 redis
```
当Docker本地没有redis镜像的时候,会自动先下载该镜像的最新版本。redis镜像内容见:Dockerfile/redis。然后,我们可以启动Web App:

$ sudo docker run --rm -it -p 3000:3000 --name ProtoWebApp --link redis:redis -v "$(pwd)":/webapp -w /webapp -e NODE_ENV=production node npm start

[quote] ProtoWebApp@0.0.0 start /webapp
[quote] node ./bin/www[/quote][/quote]

info: Hello again distributed logs
Reply: OK
Reply: 0
Reply: 0
2 replies:
0: hashtest 1
1: hashtest 2

比上面启动Node.js的方式,多了:`--link redis:redis`,冒号前的`redis`表示镜像名称,后面的`redis`表示这里使用的别名。

另外,创建Client的代码有点不同:

var redis = require("redis"),
client = redis.createClient(6379, "redis");

其中`redis`是redis容器的别名。或者讲究点也可以这样:

var redisHost = process.env.REDIS_PORT_6379_TCP_ADDR;
var redis = require("redis"),
client = redis.createClient(6379, redisHost);

源代码见这里:https://github.com/MarshalW/ProtoWebApp/tree/m4

连接MongoDB
执行命令,启动mongoDB:

sudo docker run -d -p 27017:27017 -v "$(pwd)"/db:/data/db --name mongodb dockerfile/mongodb

数据库文件保存在当前目录下的db目录下,如果不存在目录的话会自动创建。

在`package.json`中加入:

"mongoose":""

在`app.js`代码中加入:

//测试mongoDB
var mongoose = require('mongoose');
mongoose.connect('mongodb://mongodb/test');

var Cat = mongoose.model('Cat', { name: String });

var kitty = new Cat({ name: 'Zildjian' });
kitty.save(function (err) {
if (err) console.log(err);
console.log('meow');
});

执行Docker命令:

$ sudo docker run --rm -it -p 3000:3000 --name ProtoWebApp --link redis:redis --link mongodb:mongodb -v "$(pwd)":/webapp -w /webapp -e NODE_ENV=production node npm start

[quote] ProtoWebApp@0.0.0 start /webapp
[quote] node ./bin/www[/quote][/quote]

info: Hello again distributed logs
js-bson: Failed to load c++ bson extension, using pure JS version
Reply: OK
Reply: 0
Reply: 0
2 replies:
0: hashtest 1
1: hashtest 2
meow


源代码见这里:https://github.com/MarshalW/ProtoWebApp/tree/m5

本文收发于我的个人博客:http://blog.shiqichan.com/Deploying-Nginx-with-Docker/

Docker网络管理的未来

jeffsui 发表了文章 • 0 个评论 • 7491 次浏览 • 2014-12-16 13:00 • 来自相关话题

【编者的话】作者是一个极客,从Docker的0.7版本开始就关注了Docker的网络问题,本文虽然带有些感情色彩,但也不难看到作者对Docker的痴迷程度,不难看出他那颗想让Docker更好的心。文章分析了Docker的网络历史,对相关的解决方案发表了自己的看 ...查看全部
【编者的话】作者是一个极客,从Docker的0.7版本开始就关注了Docker的网络问题,本文虽然带有些感情色彩,但也不难看到作者对Docker的痴迷程度,不难看出他那颗想让Docker更好的心。文章分析了Docker的网络历史,对相关的解决方案发表了自己的看法,作者期待Docker官方能做出最正确的决定。

最近有很多关于Docker网络管理的讨论,对这个问题大家众说纷坛。引起争论的主要原因是近年来使用Docker的人越来越多,用户逐渐意识到Docker的网络缺陷亟待解决。当然,实际情况也是这样,目前Docker的网络能力严重不足,不支持复杂的设置,现在Docker的网络模型存在性能问题且不易扩展。不过对于一个基本的应用而言Docker的网络模型已经很不错了。然而,我们不能永远停留在使用“基本应用”的级别上,伴随着云计算和微服务的普及,这些还远远不够。作为libcontainer的贡献者之一,我想通过本文,发表一些自己的观点。

首先我需要先聊聊一些和网络相关背景知识。一开始的时候,Docker使用者和开发者就意识到Docker网络模型的不足,因为他们需要给Docker容器分配更多的IP地址,而使用LXC作为容器引擎却不会为这个问题而感到苦恼。容器已经存在了相当长一段时间,只是由于Docker的出现好多人才去学习Linux的命名空间(namespace),包括网络的命名空间,它是Linux容器网络的基石。Docker Tinkerer Extraordinaire 写了很多的博客并开发了pipework工具,它可以帮助了解Docker的网络以及如何在Docker中构建复杂网络。虽然pipework很强大,但它也仅仅只是一个第三方的工具罢了,我们希望Docker原生的支持。

我从Docker 0.7版本开始就关注它的网络问题了,但我并不是直接一头扎进源码里研究。相反,我首先尝试研究LXC网络,我希望它可以帮助我找到问题的关键点并运用到Docker上。我联系了Jerome并且对在未来在Docker中嵌入golang-pipwork hack达成了共识。接下来就是个漫长的故事。时间过去七个月了,我们并没有在Docker-network-land这个项目上投入太多的精力,在GitHub上也鲜有人讨论网络相关的问题。当我打开那些需要解决的问题的链接的时候,我觉得是时候需要改变了。Docker们关心的是那些优先级比较高的问题因为我们已经有了pipework以及pipework衍生的工具。与此同时,越来越多的实用性工具使得我们能突破Docker的网络局限。人们不再关心Docker的网络问题,而只是通过一小部分人修复那些已经存在的问题并添加一些新功能。

转眼过了几个月的时间,我们最终决定开始改变现状。我们向官方提出了网络方面的建议并建立了一个关于libnetwork的聊天室,尽管这些距离我们某些不成熟的想法有些遥远。现在参与讨论的人越来越多。在我的观点看来,这对Docker来说是至关重要的。值得欣慰的是社区里很多人也开始意识到这个问题。

Docker的网络问题是极其复杂的,包括表面的和深层次的。它会涉及到非常多的项目,小到本地开发环境,大到类似牛逼的Kubernetes项目。当你阅读了Kubernates关于网络方面的设计文档后,你会发现一些好点子。在过去的一年时间里,我们开发了很多工具和类库去解决网路问题。我真的希望正在进行的讨论不会影响(fuck)到我们现有的工作,而是能够为新人创造更好的环境。我之所以使用Fuck这个词是因为我曾见识过一个坏决定是如何让所有人失望的,这也是我对Docker的一点担心。也许这些都只是人生经历罢了,正如俗语有云:历史交不给我们什么,所以我只是替古人担忧罢了。

对于我来说Docker不仅仅意味着软件交付,不仅仅意味着DevOps。它是另一种开发工具。对我而言,Docker应该是一个工具,而且也许更重要的是一个平台。嗯,是开放平台,并且不是我们经常讨论的那种软件平台。如果Docker准备让用户或者公司在现有的平台上构建其解决方案,那它就不应该依赖其它项目。我希望官方不会这样做,因为Docker的伙计们已经知道摆脱依赖LXC并使用自己的libcontainer项目来替代。类似的处理思路应该用到网络问题的上。

目前看到有一些计划是打算将OVS项目关联到Docker上来,从Linux Kernel 3.3开始,OVS项目就是内核的一部分。当我听到这个的时候我觉得是不是脑袋让驴踢了。首先声明我并不是反对使用OVS,实际上,它是一个非常不错的网络工具套件。它的设置比较复杂,对于新手来说有一个陡峭的学习曲线,但是一旦学会,OVS就可以帮你事半功倍。关于这个话题我听到的一个讨论是:“如果OVS工作在Docker上,那么工作一切都变得很美好”。让我告诉你,亲们:如果让我花费大量时间学习它,最后的结果只能是:“还好,可以用”。我并不想说的那么愤世嫉俗,实际情况是在某些常用环境下OVS会崩溃。因此,使用OVS只是一种疯狂的想法罢了。我并不想大家都认同我的说法。是的,你可以什么都不做,也可以把他当做日常基础工作。你可以让系统管理员和网络工程师很开心,但是不全是这样,同时也会让开发者很孤独。这是一个复杂的话题,当然解决问题并非只有一种方法(没有银弹),所以我们不奢望真的有银弹罢了。

这个帖子并不是讨论是否将OVS成为Docker的一部分。我选择谈到OVS是因为,这可能是解决Docker网络问题的方案之一。我们讨论的范围有且不限于Docker的第三方项目,无论它是否开源。截止到目前,Docker们已经做了一些工作去避免这种问题的出现。很重要的一点是我们之前谈到的问题:避免对某个项目的依赖。一旦你决定使用某个项目,你的注意力就不得不集中在避免损害已经作为有机整体的平台构建项目的相互依赖的问题上。正如我们现在讨论的项目例如 flannelweavedocket等,还有更多的新增的项目平台带来的众多依赖项目上。

目前有一个基于可插拔的网络后端设置看起来是个不错的建议。但是这还需要一点时间,直到有基于硬件的可插拔的架构设计而不仅仅是解决网络问题,还更多的Docker参与和时间的检验。这个改变发生在Docker的核心,目前正在从移动终端转移到网络部分。我认为,给Docker们建立一个健壮的默认的后台,而不是给用户一些列的解决方案,强迫他们使用固定的路径,是一个比较稳妥的做法。不可避免的我们会对其他项目引用和依赖,这将不会影响目前的Docker用户,并且不会给未来的Docker用户带来影响。我们都明白不可能让每个人都满意,但是你可以创建一个友好的环境,用来建立自己的解决方案,这样使得不同用户可以共同工作而不会相互影响。如果你和我一样加入可插拔的API项目,那么我们就是在同一条船上的人了。

说起Docker网络的未来,我真的很兴奋,我非常期待Docker能做出最正确的决定。最重要的是,我希望本文能激发更多的人能参与其中一同完善这个项目。


原文地址:http://containerops.org/2014/11/11/future-of-Docker-networking/

10x系列之Docker在Clay.io

sean 发表了文章 • 0 个评论 • 4890 次浏览 • 2014-12-16 11:49 • 来自相关话题

【编者的话】近日,Clay.io的Zoli Kahan开始了“10X”系列博文的撰写。通过这个系列博文,Zoli将分享如何只使用一个很小的团队支撑Clay.io的大规模应用。本文是整个系列的第三篇,DockerOne接下来将会对整个系列文章进行翻译。 ...查看全部
【编者的话】近日,Clay.io的Zoli Kahan开始了“10X”系列博文的撰写。通过这个系列博文,Zoli将分享如何只使用一个很小的团队支撑Clay.io的大规模应用。本文是整个系列的第三篇,DockerOne接下来将会对整个系列文章进行翻译。
简介

Clay,我们的部署过程非常有趣。真的!因为我们使用Docker。Docker是一个用于简化应用隔离与部署的容器化工具。其基本思路是,Docker会在一个虚拟的隔离环境中运行你的应用,这有点像虚拟机,但没有额外开销。你以一个“基础镜像”起步,然后使用一个Dockerfile描述如何创建一个“容器”。
综述
docker-diagram.png

我们的部署过程是这样的:

    []将所有要发布的代码合并到git的`master`分支[/][]用`git tag`打上发布标签(比如 v1.0.0)[/][]构建Docker镜像(代码锁定)[/][]用`docker tag`打上发布标签(比如 v1.0.0)[/][]将Docker镜像推送到registry[/][]更新集群容器版本(零停机)[/]
- 确认备用容器正在运行 - 升级主容器 - 等待新的主容器上线 - 升级备用容器
    []更新生产集群容器版本(零停机)[/]
- (与上同)这个过程确保了在过渡环境和生产环境中运行的是完全相同的代码,同时允许我们在发生错误时回滚到上一个Docker容器发布版本。 Clay.io的Dockerfile 这是来自我们的移动应用的一个示例Dockerfile(源码):
FROM dockerfile/nodejs:latest# Install GitRUN apt-get install -y git# Add sourceADD ./node_modules /opt/clay-mobile/node_modulesADD . /opt/clay-mobileWORKDIR /opt/clay-mobile# Install app depsRUN npm installCMD ["npm", "start"]
这个文件不言自明。它只是简单的从当前目录复制源码到容器中。环境变量将用于引入敏感的或动态的配置。重点说明一下:`npm start`实际上是在为生产环境编译并压缩代码:
// package.json{  "scripts": {    "build": "node_modules/gulp/bin/gulp.js build"    "start": "npm run build &&              ./node_modules/pm2/bin/pm2 start ./bin/server.coffee                -i max                --name clay_mobile                --no-daemon                -o /var/log/clay/clay_mobile.log                -e /var/log/clay/clay_mobile.error.log",  }}
这是因为我们需要使用生产环境变量重新构建静态文件。请访问我们的GitHub查看更多示例:github.com/clay.io Docker镜像的基本部署 在Clay,我们将镜像托管在docker registry上。因为Docker,部署我们的应用到过渡环境和生产环境中非常简单。整个过程(从未标记容器,到过渡环境,由Ansible自动完成)如下:
# Local machine / Build serverdocker build -t clay/mobile .docker push clay/mobile
# Staging / Production serverdocker pull clay/mobiledocker run    --restart on-failure    -v /var/log/clay:/var/log/clay    -p 50000:3000    -e CLAY_MOBILE_HOST=XXXX    -e CLAY_API_URL=XXXX    -e FC_API_URL=XXXX    -e NODE_ENV=production    -e PORT=3000    --name mobile    -d    -t clay/mobile:VERSION
(注意:49,152 - 65,535端口通常用于私有应用) 零停机更新 你可能注意到在上述启动脚本中,我们使用PM2来处理集群多个服务器进程。PM2支持零停机更新,不过因为它存在于容器内,而我们从不在运行时修改容器内代码,所以我们没使用这个功能。PM2只是单纯的用于获取多个服务器的核心。零停机更新的关键点在于运行两个服务器进程。一个主进程和一个备用进程。我们通过给两个容器部署分配不同的端口实现这一点:
docker run ... -e PORT=50000 --name mobiledocker run ... -e PORT=50001 --name mobile-backup
HAProxy负责在主服务器宕机时将流量重分配到备用服务器上:
# example haproxy.cfgbackend mobile  mode http  balance roundrobin  server app1 x.x.x.x:50000 check  server app1b x.x.x.x:50001 check backup  server app2 x.x.x.x:50000 check  server app2b x.x.x.x:50001 check backup
后续将有篇关于HAProxy的文章,介绍更多关于我们是如何使用HAProxy在服务器间进行负载均衡的详情。以下部署过程将完全由Ansible自动完成:[list=1][]确认备用健康容器状态(Ansible)[/][]`docker pull clay/mobile:v1.0.0`[/][]杀死主容器(网络请求自动重路由到备用服务器)[/] - `docker rm -f mobile` [list=1][]更新主容器,并重启[/] - `docker run ...` [list=1][]一旦主容器恢复,网络请求将移回到主服务器[/][]杀死并更新备用容器[/]
- `docker rm -f mobile-backup && docker run ...`

如果发生了任何错误,只要简单的恢复到上一个镜像版本:
`docker run -t clay/mobile:v0.0.12`

结语

如果你错过了之前的10x文章:可以点击下面的链接阅读:

Architecture中文翻译
Logging中文翻译

原文:10x: Docker at Clay.io

推进 Docker 安全:Docker 1.4.0 和 1.3.3 发布

叶可强 发表了文章 • 0 个评论 • 5338 次浏览 • 2014-12-12 14:47 • 来自相关话题

【编者的话】Docker 1.4如期而至,正如DockerCon上Solomon所说,该版本主要集中在Bug修复以及平台稳定性和安全性上。Docker官方新闻详细描述了该版本的改进信息,本文是DockerOne对官方新闻的翻译。 我们 ...查看全部
【编者的话】Docker 1.4如期而至,正如DockerCon上Solomon所说,该版本主要集中在Bug修复以及平台稳定性和安全性上。Docker官方新闻详细描述了该版本的改进信息,本文是DockerOne对官方新闻的翻译。

我们非常高兴的宣布在今天发布 Docker Engine 1.4。它有什么特性呢?正如上周 Solomon Hykes 在 DockerCon Europe 描述的那样,这个版本主要集中在Bug 修复和平台稳定性上,且超过 180 个Bug修复提交被合并!Docker 1.4 也添加了 Overlay Filesystem,作为一个新的试验性的存储引擎。(请看发行说明bump 分支)。

今天,我们同时发行了 Docker Engine 1.3.3,修复了 3 个Bug(请看报告)。当然在版本 1.4.0 中也包含这些改进。这里是关于这些Bug的详细信息:

* 在 2014 年 11 月 24 日,我们发行了 Docker 1.3.2 来修复这些严重的问题(issues ),恶意的镜像可以利用该问题来突破 Docker 容器。请看我们的安全公告获取更多信息。
* 在发行 1.3.2 之后,我们发现额外的Bug能被恶意的 Dockerfile、镜像、registry利用来攻陷主机,或者是假冒官方镜像。
* Docker Engine 1.3.3 和 Docker Engine 1.4将会修复以上Bug。所有的用户建议升级到 Docker Engine 1.3.3 或更高的版本。请看升级说明文档。
* 请注意这些缺陷仅仅影响那些下载和运行了恶意镜像,或者是从恶意 Dockerfiles 构建的镜像的用户。用户可以通过仅仅从受信任的源下载、构建、运行镜像来免遭恶意内容的伤害。另外,我们建议你:

- 使用 AppArmor 和 SELinux 来运行 Docker Engine 来提供额外的隔离
- 映射相互信任的容器组来隔离机器和 VMs。

推进 Docker 安全

下面是我们的安全公告和随后的 Docker Engine 1.3.3 发行版。我想分享一些我们关于安全的想法和计划。对于 Docker 来说,安全是非常重要的,直接体现就是:

* 当确定漏洞时,努力迅速解决。
* 我们的用户和他们的应用通过我们的发展蓝图来加强平台安全。
* 与我们的贡献者和生态系统合作伙伴合作来定义一系列关于 Docker 安全的最佳实践

具体地说,我们努力专注于以下事情:

1. 产品和生态系统。 Docker Engine可以充分利用OS的安全策略以及隔离特性。在 Linux 的 namespaces、capabilities和基于 libcontainer 或 lxc 实现的 cgroups 支持下,这是可插拔式的。在将来,我们会给第三方的执行引擎插件更多的机会,希望它们可以为用户提供更加细粒度服务。在系统级别的支持下,Docker 已经合并集成了 SELinux 和 AppArmor。Red Hat、Canonical以及其它公司都在帮助我们提高容器的安全性。从 1.3 版本开始,我们已经在 Docker Hub 的官放仓库中添加了签名的 Docker 镜像,这只是我们规划的安全链上的第一步。你可以在这详细阅读我们的信任制度建议并鼓励你添加改进
2. 安全审计、报告和响应。我们会做自己的安全测试,同时让一个私人安全公司来审计和执行渗透测试。Issues 也被我们的活跃用户和开发者社区接收。所有的问题报告都会被迅速分类,严重的 issues 会启动一个 immediate 响应。我们的目标是快速并安全的修复在用户手中的当前稳定版本。修复,一旦准备好,会开始发送一个早期的公开通知列表来 review 和为供应商准备提前公开。这个列表包含 Linux 发行版和云服务商。我们继续开发和更新我们的实践,当我们学习到更多。
3. 公开透明。我们践行有责任的披露。在不影响用户的前提下,在不影响用户的前提下,我们披露Docker的安全问题并及时提供相应的安全更新。

随着我们的发展,我们将持续在我们的安全团队、贡献、工具和流程上投入。该投入将使得 Docker 更安全,帮助它成为我们安全可信的伙伴。

你也可以提供帮助!请报告问题给 security@docker.com。想了解更多的信息,请移步。

Docker Compose介绍

DockOne 发表了文章 • 5 个评论 • 34301 次浏览 • 2014-12-08 14:14 • 来自相关话题

Docker Compose是Docker编排服务的最后一块,前面提到的Machine可以让用户在其它平台快速安装Docker,Swarm可以让Docker容器在集群中高效运转,而Compose可以让用户在集群中部署分布式应用。简单的说,Docker Comp ...查看全部
Docker Compose是Docker编排服务的最后一块,前面提到的Machine可以让用户在其它平台快速安装Docker,Swarm可以让Docker容器在集群中高效运转,而Compose可以让用户在集群中部署分布式应用。简单的说,Docker Compose属于一个“应用层”的服务,用户可以定义哪个容器组运行哪个应用,它支持动态改变应用,并在需要时扩展。
docker-compose_w_450.png

使用Compose的第一步是使用YAML文件来定义容器应用的状态:

containers:
web:
build: .
command: python app.py
ports:
- "5000:5000"
volumes:
- .:/code
links:
- redis
environment:
- PYTHONUNBUFFERED=1
redis:
image: redis:latest
command: redis-server --appendonly yes

上面的YAML文件定义了两个容器应用,第一个容器运行Python应用,并通过当前目录的Dockerfile文件构建。第二个容器是从Docker Hub注册中心的Redis官方仓库中构建。links指令用来定义依赖,意思是Python应用依赖于Redis应用。
定义完成后,通过下面的命令来启动应用:

% docker-compose up

简单吧?通过YAML文件定义的容器应用已经成功启动起来,启动过程会按照YAML的配置严格运行。Python容器通过Dockerfile自动构建,同时从注册中心拉取Redis容器构建。 links指令关注的是Python和Redis容器之间的依赖关系,Redis容器是最先开始构建,紧随其后的是Python容器。

Docker Compose应用目前还在紧张开发中,感兴趣的读者可以关注GitHub动态

Docker Swarm介绍

DockOne 发表了文章 • 0 个评论 • 10837 次浏览 • 2014-12-07 20:47 • 来自相关话题

Docker Swarm是一个Dockerized化的分布式应用程序的本地集群,它是在Machine所提供的功能的基础上优化主机资源的利用率和容错服务。具体来说,Docker Swarm支持用户创建可运行Docker Daemon的主机资源池,然后在资源池中运 ...查看全部
Docker Swarm是一个Dockerized化的分布式应用程序的本地集群,它是在Machine所提供的功能的基础上优化主机资源的利用率和容错服务。具体来说,Docker Swarm支持用户创建可运行Docker Daemon的主机资源池,然后在资源池中运行Docker容器。Docker Swarm可以管理工作负载并维护集群状态。
logo.png

Docker默认调度器会根据Docker容器的工作负载以及集群中主机的可用资源,使用bin pack自动优化工作负载。 例如,调度一个需要1G内存的Redis容器:

% docker run -d -P -m 1g redis

为了支持特定的需求和基于策略的调度,Docker Swarm还提供了标准和自定义约束。比如为了保证好的IO性能,用户可能想在SSD上运行MySQL容器,这个时候可以定义如下约束:

% docker run -d -P -e constraint:storage=ssd mysql

docker-swarm_w_450.png

除了资源优化,Docker Swarm可以保证应用的高可用性和容错性。Docker Swarm会不断的检查Docker Daemon所在主机的健康状态。当某个主机不可用时,Swarm就会将容器迁移到新的主机上。
Docker Swarm的亮点之一是它可以在应用的生命周期内扩展,也就是说当应用从一个主机扩展到2个、20个或者200个的时候,用户可以保证接口的一致性。
同样,和Machine一样,Swarm的架构是可插拔的,系统已经包含一个默认的调度器。其它的厂商可以实现自己的调度器。
可能上面的解释不太好理解,读者可以看完例子后再回来看上面那段话。或者可以看看作者(Andrea Luzzardi)在DockerCon上的演讲稿

CoreOS的集群中的Discovery服务器搭建,有朋友在这方面有所研究不?

回复

jamlee 回复了问题 • 2 人关注 • 1 个回复 • 4537 次浏览 • 2014-12-07 20:40 • 来自相关话题

为什么CoreOS和Docker的分手是命中注定的

DockOne 发表了文章 • 0 个评论 • 5523 次浏览 • 2014-12-04 20:15 • 来自相关话题

本文翻译自Why Docker and CoreOS’ split was predictable,原文作者Daniel Compton。中文翻译来自七牛云存储&version=11020012&pass_ticket=lkf9QVxqd5MMciJiV7BN ...查看全部
本文翻译自Why Docker and CoreOS’ split was predictable,原文作者Daniel Compton。中文翻译来自七牛云存储&version=11020012&pass_ticket=lkf9QVxqd5MMciJiV7BNzF4GrbLNzvUjAxWzbjNzLd3M7SeuiWN4bxF2GDa%2B8lre),DockerOne基于七牛云的翻译进行了整理。

韦恩·格雷茨基曾说过:“我总是溜向冰球将达到的点,而不是追逐它曾在的地方。

关于Docker是否应该扩大产品的边界以扩张CoreOS的集群管理范围的争论由来已久,这也直接导致了CoreOS开发了自己的容器Rocket来与Docker争雄。这种现象可以被Clayton Christensen教授的 Law of Conservation of Modularity 一书中的观点合理地解释:

0.jpeg

“根据我们的研究,存在这样一种现象,当价值链上的一种产品在商品化的同时,与此同时在价值链上肯定会有一种当前产品非商品化的趋势,这种相互作用的进程就意味着,当新的破坏性浪潮冲刷一个行业时,差异化能力仍然在价值链上不断的转移着。当发生这种情况时,那些将自身定位再不够完善的价值链区间的企业就能够盈利”



-Clayton Christensen, 第六章:创新者的方法。

关于Docker和CoreOS之间的这点事在科技界并不新鲜,在计算机产业发展的初期就曾经发生过。当差异化能力在价值链上不断的转移时,力图拥有这种能力的人之间就会产生各种对抗。就像在冰球比赛中一样,总有人滑向价值将要产生的地方。

历史不会重演,但总是惊人的相似。起初,大型机的发展总是差强人意,所以被整体设计、制造和出售是一个大的趋势。IBM在这一整合的历史趋势中获得了大部分利润,由于它的供给能够填补当时这种趋势中的不足。几年后,小型机和大型机已经发展得足够完善了。这时候利润从组装整个机器的整合资源者(如IBM和康柏)转移到各个部件的生产商了:操作系统(微软),处理器(Intel),存储器和驱动器。现在又到了整合资源的商家通过填补整合资源的空白来获取利润的时代了。

在台式机的领域里,处理器和操作系统一开始不那么令人满意,因此价值转移至此并不断被持续改善。但存储器和驱动器就不那么幸运。当他们发展得足够好并且能够进行模块化操作的时候,利润早已经被生产DRAM的厂家瓜分大半。

在云服务领域,截至2013年云服务商提供的虚拟机服务已经足够完善而且成功商品化。发展得并不尽如人的方面是应用的重构、部署和多服务器的管理。这时涌现了一大批工具如puppet、chef 和ansible,但是所有工具的表现不分伯仲。直到王者Docker在Github上的出现才打破了现有的格局。

从模块化和整合化的方面来说,我们可以认为Docker被设计的初衷是在独立封装和在任何平台都可以同步运行。Docker将操作系统、虚拟机、物理机和基于上面的操作整合起来进行商品化。同时提供了一系列的API,使得其他人能够基于这些API进行操作。Docker不能商品化的部分是数据中心,我们稍后会解释为什么特别强调这一点。

从一个开发者的角度,把应用封装在Docker的意义在于你可以你整个云服务作为一个模块进行操作,这其中的模块只是一个可以被替代的商品。Docker的伟大之处在于你可以任意地把你的应用进行迁移而无需做出其他改动。这对于谷歌这样的云服务的提供者可不是一个好消息,因为用户的迁移成本变得非常低。这时代,价值就从提供虚拟环境VM的云服务商流向Docker。

Docker对于开发者的意义在于,封装应用只需要Docker就够了。可以预见的是将会很快出现一大批公司提供基于Docker的无差异的整合服务。最著名的无疑是CoreOS。CoreOS提供了分离式的Linux版本服务和基于容器Docker的集群服务。CoreOS剥离了虚拟机和容器Docker,并以单一集群和商品化的数据中心进行代替。价值再次进行转移,从Docker转向整合Docker之后提供的服务。无论他们承认与否,CoreOS与其友商都是其他云服务商的潜在威胁:他们要将云服务及其建立在之上的整合平台进行商品化

感受到这样的威胁,如果采取调整自己的服务以适应Docker的发展这样的策略对于谷歌这样的云服务提供商来说并不奇怪。他们的服务可以基于自己的硬件平台并将Docker整合在自己的服务里进行管理,这可以使价值重新分布。但令人大跌眼镜的是,谷歌又推出了自己的容器集群管理工具 Kubernetes,直到现在我还是不能理解。

那最后留给Docker的是什么呢?从一开始它提供了一个模块化的组件供其它应用使用。这对于其他组件是有很大价值的,但对Docker却没有什么价值,因为这个过程并不能获得极大的利润。完全商品化并不是一条好的出路,对于Docker的投资人来说肯定也不会带来极高的回报率。

所以CoreOS肯定会把Docker当作一个商品的构成要素,当Docker意识到自己的价值不过是被像CoreOS这样的企业作为一个工具来创造价值的时候,Docker肯定不能只是继续停留在OS层面提供价值。对于Docker来说,惟一的出路是向上一层发展。基于Docker进行构建和运行并且进行管理的整合式集群服务对Docker来说才有意义。

CoreOS对这种变化是非常在意的,因为Docker对于他们来说 ,在开发者中间,是一个极大的潜在竞争者。最自然的反应就是构建一个新的容器作为和Docker进行博弈的工具从而支持他们本来自己的服务。Rocket从出生开始相对于Docker就有技术方面的优势,这是因为它本身就是CoreOS制造用来抵挡来自Docker的威胁。

在不久的将来,集群管理也将会被完全商品化,价值将会流到别的地方,这种循环又会重新上演。这种把戏,跟打冰球没什么两样。

如何学习Docker

绿剑色影 回复了问题 • 27 人关注 • 9 个回复 • 31775 次浏览 • 2015-11-11 10:30 • 来自相关话题