Docker Workflow(一):一个可用于生产环境的Docker工作流

本文讲的是Docker Workflow(一):一个可用于生产环境的Docker工作流,【编者的话】作者工作于墨西哥IIIEPE研究院,他将通过一系列文章,为我们逐一讲述他们在Docker实际应用过程中的经验与教训,给后来者提供一些参考。本文主要介绍了他基于Docker的开发工作流,包括GitLab、Jenkins、Registry、Nginx。

Docker现在已经两岁了(译者注:Docker于2013年3月13日首次发布),IIIEPE已经在生产环境中使用Docker3个来月。在此,我分享一些我们的经验和设计的工作流。

我们运行着多个使用Drupal、PHP和Node.js的网站,我们的目标是使用Docker运行所有的应用,因此我们设计了以下工作流:

  • 所有开发人员使用Docker来创建应用。
  • 我们的GitLab实例配置了Webhook,当检测到一个新的推送时,它将命令Jenkins运行一个任务。
  • 每个Jenkins任务都包含相同的布置:从GitLab中克隆最新代码,运行测试,登录到我们的私有Docker Registry,使用最新代码构建一个新的镜像,然后将镜像推送上去。
  • 最后,我们的编排软件Maestro-NG将部署新版本的镜像。
  • 我们的负载均衡器将检测这些变化,并重载新的配置。

每一个步骤都需要几天的规划、测试和工作来设计基本准则。

我们做的第一件事是构建满足自己要求的基础镜像。镜像发布到Docker Hub中,它们包含了除了应用本身之外所有用于运行应用的东西。每次修改其中一个基础镜像,我们就会运行一个Jenkins任务来拉取新镜像,并触发后续任务来重新构建依赖此基础镜像的所有镜像。

创建完镜像之后,我们需要为所有应用定义一个标准结构。我们所有的应用都使用以下结构来组织:

/application
/logs
/files
Dockerfile
fig.yml.example
docker-compose.yml.example
Makefile

/application目录是应用的根目录。

/logs和 /files目录用于开发,以便应用可以写入日志和文件。这两个目录会被Git忽略,并在生产环境中完全排除。

Dockerfile是Jenkins用于构建镜像的文件,开发人员几乎不需要接触这个文件,后面详述。

fig.yml.exampledocker-compose-yml.example是开发人员用于启动应用的文件。这二者均不用于生产环境,当开发人员克隆一个项目时,他需要复制这个example文件并填入他/她的值。

Makefile是拼图的最后一块,通过它我们可以拥有一个标准的命令集用于所有应用,并对开发人员隐藏各种各样的复杂性。

Dockerfile

每个应用的Dockerfile与其它应用非常类似,这个文件的最重要工作就是构建包含所有待部署代码的最终镜像。我们来看一个例子:

FROM iiiepe/nginx-drupal6

ENV MYSQL_ENV_MYSQL_DATABASE somedb  
ENV MYSQL_ENV_MYSQL_USER root  
ENV MYSQL_ENV_MYSQL_PASSWORD 123  
ENV MYSQL_PORT_3306_TCP_ADDR localhost  
ENV MYSQL_PORT_3306_TCP_PORT 3306  
ENV BASE_URL http://example.com  
ENV DRUPAL_ENVIRONMENT production

EXPOSE 80

RUN usermod -u 1000 www-data  
RUN usermod -a -G users www-data

ADD ./application /var/www  
RUN chown -R www-data:www-data /var/www  

Dockerfile依赖于我们构建的基础镜像,在此之上,它只是设置了一些环境变量默认值、声明要暴露的端口,并将应用代码添加到/var/www

正因为我们构建镜像的这种方式,在Jenkins和开发人员之间唯一的差别是,Jenkins将添加整个应用目录到/var/www中,而开发人员只是映射一下目录。

接下来这个是Docker Compose,他非常酷。

mysql:  
image: mysql:latest
expose:
- "3306"
ports:
- "3307:3306"
environment:
MYSQL_DATABASE: database
MYSQL_USER: root
MYSQL_PASSWORD: admin123
MYSQL_ROOT_PASSWORD: admin123
web:  
image: iiiepe/nginx-drupal6
volumes:
- application:/var/www
- logs:/var/log/supervisor
- files:/var/www/sites/default/files
ports:
- "80:80"
links:
- mysql:mysql
environment:
BASE_URL: http://local.iiiepe.net
DRUPAL_ENVIRONMENT: development

Docker Compose用此文件来初始化。在本例中,我们定义了一个应用,它包括两个容器:一个MySQL容器和一个Web容器。

MySQL容器定义了mysql镜像要使用的环境变量。同时将宿主的3307端口映射到窗口的3306端口上。这允许我们使用任何客户端访问MySQL服务器。

web容器使用了与Jenkins构建最终镜像时使用的相同镜像(见上述Dockerfile),但它同时共享了一些数据卷。在宿主和容器间共享的卷有应用、文件和日志。这实际是开发环境和生产环境间最大的改变:在生产环境中,容器的代码是在镜像中的,这允许我们在任何服务器上启动容器;而在开发环境中,目录只是共享的,因此在应用目录里,任何新的文件或对文件的修改都将即时地反映到容器里。

BASE_URL变量指向了http://local.iiiepe.net,这不是个真实的地址,只是用于标准化应用访问的一个方式。因为我们有些人使用Mac和Boot2Docker,我们需要一个标准的地址以便所有人可以将其写入到/etc/hosts文件中。

我的Mac上的/etc/hosts是这样的:

127.0.0.1    localhost
192.168.59.103    local.iiiepe.net

在一台Linux机器上,看起来是这样的:

127.0.0.1    localhost local.iiiepe.net

最后,我们定义了两个环境变量来决定应用的配置文件的一些设置。

自定义设置

Drupal需要一个settings.php来存储数据库信息,包括密码。该文件将被Git忽略,以免将你的密码提交上去,我们决定修改这个文件,让它使用环境变量并将其提交。

以下是一个Drupal 6网站的settings.php里的重要部分:

$username = getenv("MYSQL_ENV_MYSQL_USER");
$password = getenv("MYSQL_ENV_MYSQL_PASSWORD");
$host = getenv("MYSQL_PORT_3306_TCP_ADDR");
$port = getenv("MYSQL_PORT_3306_TCP_PORT");
$database = getenv("MYSQL_ENV_MYSQL_DATABASE");

$db_url = 'mysql://' . $username . ':' . $password . '@' . $host . '/' . $database;

正如你所看到的,没有密码会被提交。密码和其它敏感值将通过ENV变量注入。

有些网站使用Apache Solr作为搜索引擎,但在开发时,我们不希望能写入到Apache Solr,因此需要一个类似DRUPAL_ENVIRONMENT的ENV变量,完成类似下面的settings.php文件的事情:

$conf = array();
if(getenv("DRUPAL_ENVIRONMENT") === "development") {  
// Disable apache solr writting
$conf["apachesolr_read_only"] = 1;
}

Makefile

由于命令很长,使用Docker非常不便,因此Docker Compose(fig)对此很有帮助。我们更进一步尝试让事情变得更简单一些。

这是我们使用在一个Drupal网站上的Makefile:

CURRENT_DIRECTORY := $(shell pwd)

start:  
@fig up -d

clean:  
@fig rm --force

stop:  
@fig stop

status:  
@fig ps

cli:  
@fig run --rm web bash

log:  
@tail -f logs/nginx-error.log

cc:  
@fig run --rm web drush cc all

restart:  
@fig stop web
@fig start web
@tail -f logs/nginx-error.log

.PHONY: clean start stop status cli log cc restart

使用Makefile比使用Docker Compose或Fig简单得多,因为我们可以创建类似make cc的快捷方式来运行类似drush cc all这样频繁使用的命令。

有关Makefile的最后一点说明是:我们依然使用Fig。因为在我们设计这个工作流时,Docker Compose还不可用,而且我们团队里的一些开发人员还在使用它,我们决定为Docker Compose建立名为Fig的符号连接,名称更短且更实用。安装Docker Compose后,你可以删除fig并创建符号连接:

sudo rm /usr/local/bin/fig  
sudo ln -s /usr/local/bin/docker-compose /usr/local/bin/fig  

走的弯路

我们走过一些弯路,我将在别的文章中做介绍,不过有一个我想特别说一下。使用Docker最大的好处是,开发人员可以在与生产环境相同的环境上运行应用,且只损失一点点性能。

我看过一些文章,说他们在Docker之外做开发,然后在需要部署时构建镜像并发送到生产环境。如果你这么做,那你就错了,因为你开发所用的环境与生产机上运行的不一致。不要每次都构建镜像,相反的,在宿主和容器间共享卷,让别人在你每次推送时构建镜像。

未完待续……

文章还远未结束,不过它已经太长了。我们依然需要说明我们是如何整合Maestro-NG、配置Jenkins以及负载均衡器是如何工作的。咱们回见!

原文链接:A production ready Docker workflow(翻译:梁晓勇 校对:李颖杰)

原文发布时间为:2015-03-26

本文作者:sean

本文来自合作伙伴DockerOne,了解相关信息可以关注DockerOne。

原文标题:Docker Workflow(一):一个可用于生产环境的Docker工作流

时间: 2024-12-21 22:08:05

Docker Workflow(一):一个可用于生产环境的Docker工作流的相关文章

技术雷达:Docker能用于生产环境了,机器学习还远着呢!

IT圈从来都是热闹的,各种新技术总是层出不穷.但是,不管这些技术如何热,作为企业或者开发者都要审慎地看待他们,这些技术的发展目前到底处于什么阶段?能否能够应用于生产环境? 在最近一期的ThoughtWorks技术雷达的看点中:开源软件已经进入良性循环:Docker可以应用于生产环境:PaaS的定义仍然模糊不清,很多PaaS方法仍然不完整或者受到不成熟的框架和工具的影响:而机器学习还远着呢! 据了解,ThoughtWorks技术雷达是一份不限制行业,技术中立的前瞻性技术报告,小到一个工具和类库,大

生产环境中Docker的持久化存储模式

本文讲的是生产环境中Docker的持久化存储模式[编者的话]在生产环境中使用Docker实现持久化存储一直是业界的热点问题,本文从到配置文件.机密材料.数据库.共享数据等方面做了些探讨,文中也谈到了一些需要避免的问题以及尽量将应用设计为无状态服务的原则. 一般看法认为容器对于无状态的应用程序是很好的,但是不适合有持久化数据的有状态应用.如果这是真的,这并不是因为技术不到位,而是因为管理持久化数据和有状态应用程序的模式并不总是为人们所熟知.你面临的挑战很多不是关于持久化状态的,而是如此操作不会影响

内置编排工具且适用于生产环境的Docker 1.12 GA了!

本文讲的是内置编排工具且适用于生产环境的Docker 1.12 GA了![编者的话]对于Docker来说,内置适用于生产环境的编排工具是件大事情.本文介绍了该内嵌编排工具的拓扑机构以及管理节点与工作节点之间通信的协议,并对该版本的内容进行总结,分别为容错.规模与性能.安全. 我们感谢社区的每一位成员帮助我们顺利到达Docker1.12这个里程碑,这个版本已经为生产环境做好了准备.1.12版本是自Docker项目开始以来特性增加最大也是最先进的一个版本.包括Docker员工和外部贡献者在内的数十位

生产环境运行Docker的9个关键决策

本文讲的是生产环境运行Docker的9个关键决策,[编者的话]生产环境运行Docker并没有想象的那么简单,如何实现稳定安全的部署和扩容? 又有哪些需要考虑的关键决策? 本文就此做了一些分析和阐述,赶紧来看看吧! 也许你已经构建好了你的Rails或者基于Rack的Ruby应用.它甚至在你笔记本上的Docker容器里运行着并且团队里的其他开发者也是这样将它跑起来的.一切看上去棒极了,那么或许是时候装载它了. 不过,等一下!别急!将应用切换到生产环境中的Docker运行并没有听上去那么简单.这里面要

GlassfishV3用于生产环境的多不多?

问题描述 GlassfishV3用于生产环境的多不多? 解决方案 GlassFish 很好很强大,也听朋友说过他们公司有用在生产环境的.但是GlassFish3很新了吧,公司用的很少是比较新的东东,淘宝的jboss几乎全部是4.2的,7都出来了,没人提起解决方案二: 我们都是用的weblogic,客户有钱

【Spark Summit EU 2016】经验分享:将SparkR用于生产环境下的数据科学应用中

本讲义出自Heiko Korndorf在Spark Summit EU 2016上的演讲,主要分享了R语言以及现实场景下使用R语言进行数据分析的应用案例,并且将引领大家使用SparkR扩展R语言应用,并介绍了SparkR1.X和2.X架构,并介绍了这两个版本的SparkR分别如何获取. 除此之外,Heiko Korndorf还分享了如何使用SparkR将数据科学与数据工程集成到一起,将SparkR用于生产环境下的数据科学应用中,并对于Spark无限发展空间的生态系统进行了展望.

生产环境中使用Docker Swarm的一些建议

本文讲的是生产环境中使用Docker Swarm的一些建议[编者的话]实践中会发现,生产环境中使用单个Docker节点是远远不够的,搭建Docker集群势在必行.然而,面对Kubernetes,Mesos以及Swarm等众多容器集群系统,我们该如何选择呢?它们之中,Swarm是Docker原生的,同时也是最简单,最易学,最节省资源的,至少值得我们多了解一下.本文将介绍一些非常实用的建议. [深圳站|3天烧脑式Kubernetes训练营]培训内容包括:Kubernetes概述.架构.日志和监控,部

三个生产环境中使用Docker的案例

本文讲的是三个生产环境中使用Docker的案例[编者的话]本文为2017年初Docker线下见面会的记录,Solita.Zalando和Pipedrive公司做了Docker化经验分享,并对生产环境中使用Docker的细节进行讨论.本文还推荐了一些Docker生产环境中常使用的优秀工具. [3 天烧脑式 Docker 训练营 | 上海站]随着Docker技术被越来越多的人所认可,其应用的范围也越来越广泛.本次培训我们理论结合实践,从Docker应该场景.持续部署与交付.如何提升测试效率.存储.网

在生产环境中使用Docker必须注意的事情

本文讲的是在生产环境中使用Docker必须注意的事情,[编者的话]本文以最近非常火的希特勒怒喷Docker的视频为线索,详细分析了Docker存在的一些问题和弱点,以及在生产环境中使用Docker所要注意的方面.这些问题包括隔离性.镜像安全.Docker缺省配置.发布及部署:文章的最后分析了微软最近在容器支持方面的动作. 我们不能否认Linux容器是一个非常强大的概念,它组合了众多优秀的Linux内核功能和Docker开源工具,任何背景知识的开发者都很容易使用. 在2016年容器峰会上,Brya