在生产环境使用Docker部署应用

Docker是如今开发应用程序的不错选择;由于对于一个研发组来讲,部署一个应用不再用像之前那样繁琐的修改、设置配置文件了;由于对于Docker来讲它“屏蔽”了应用程序的运行环境,无论你使用Mac、Linux仍是Windows都能用相同的方式运行。前端

可是,当你使用Docker将应用部署到生产环境时,你会以为Docker仍是有些“弱”,至少从Ruby On Rails(ROR)的角度出发是这样的。当我查找与测试了不少不一样的部署方法与Docker镜像后发现:确实没有一个确切并且标准的部署方案。在这篇文章中我会分享一种生产环境部署ROR应用的最佳实践。linux

docker

标准web

在实际操做以前,咱们列举生产环境部署应用的标准:sql

  1. 易于使用:部署应用自己应该十分简单,否则部署新程序的过程会变得十分“恐怖”。
  2. 零服务中断:让咱们面对它——零服务中断部署ROR应用程序已经成为当今的标准。
  3. 自动化部署:我更习惯把代码推送到代码仓库,而后使用Codeship这样的工具自动测试,测试经过后自动将代码部署到生产环境的服务器。我但愿Docker能完成相同的工做。

    ## 操做就像以前我说过的,我但愿部署过程越简单越好。若是你看过Docker:Part4这个视频,可能对如下命令有所熟悉,它启动了一个叫db的容器(跑postgres数据库),以后又启动了一个叫web的容器,最后将容器“web”跟容器“db”链接起来。docker

$ docker run -d --name db training/postgres
$ docker run -i -t --name web --link db:db -p 45000:80

固然若是你照着这么作来部署程序,当你敲了不少次这样的命令后,并且保证不遗漏的敲了不少次这种命令后,你会发现这是个“坑爹的”噩梦。这就是为何会有Fig的缘由。数据库

FIG服务器

若是你用Dockerfile来定义如何生成你的容器,那么Fig则能够帮你定义整个容器的运行框架。Fig将“添加数据卷(add volumes)”、“链接容器”(link container)与“映射端口”等操做都封装到一个YAML的描述文件中;如同前面提到的CodeTV中描述的那个操做在Fig中简化成以下形式:负载均衡

web:
build: .
ports:
- "80:80"
links:
- db

db:
image: postgres
ports:
- "5432"

volumes:
- /etc/postgresql
- /var/log/postgresql
- /var/lib/postgresql

我在YAML中定义了两个容器:web与db;容器web生成自当前文件夹下的Dockerfile,向外暴露了80号端口,同时连接到了容器db。容器db生成自DockerHub的PostgreSQL镜像,向外暴露5432号端口。使用此YAML配置文件,fig能够用如下命令生成容器,而后依照配置文件的意图启动它们。框架

$ fig build
$ fig up -d

Fig会先启动被连接的容器db,这样容器web就不至于连不上数据库。-d参数表示之后台运行的方式启动容器,这样能够保证用户登出操做系统后,容器任然在运行。您能够登陆Fig的官方网站获取更多的配置信息。工具

部署

如今咱们能够很容易的启动一个Docker容器,可是怎么在生产环境下部署Docker容器呢?若是在生产环境下安装了Fig与Docker,咱们全部要作的就是克隆以前的容器镜像,而后用相同的fig命令来启动容器。可是,如今的问题是如何更新线上运行的容器。

不幸的是,Fig能够很是优雅的启动一个容器,可是它并不擅长更新并重启服务。固然,你能够在代码仓库拉取程序的更新,而后从新运行以上的fig命令来达到这个目的;可是,在容器在更新代码,从新启动的过程当中,就不能对外提供服务了。为了应对这种状况,咱们使用原生的Docker命令,并引入Nginx作反向代理(注:软负载)来解决这个问题。

咱们首先把容器监听的端口修改掉,由于Nginx须要监听80号端口。咱们这么修改:

web:
build: .
ports:
- "8080:80"
links:
- db
...

经过修改Fig的配置文件,咱们的web容器修改为监听8080号端口。而Nginx要配置成8080与8081端口的负载均衡;因此Nginx的配置以下:

upstream docker {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}

server {
listen 80;
location / {
proxy_pass http://docker;
}
}

重启Nginx后,Nginx就开始在8080与8081号端口之间作反向代理(软负载);当其中任何一个端口失效后,Nginx将请求自动转发到另外一个,直到失效后的端口恢复。这样,咱们就能从Git中拉取更新,而后运行下面的命令将其启动:

$ docker run -d --name web1 --link codetvjournal_db_1:db -p 8081:80 codetvjournal_web:latest

当咱们肯定8081号端口的web1容器启动并服务正常后,咱们就能够中止8080号端口的服务并开始为8080号端口服务进行更新了。我推荐使用原生的docker命令而不使用Fig来完成这个工做,由于这样能够避免干扰到正在运行的db容器(注:做者可能指的是以前写好的YAML,里面包含了启动db容器的配置)

咱们能够用上述方法建立不少个web容器,只要保证它们占用的端口与容器名不一样便可;同时使用Nginx在它们前端作负载便可实现不掉线的程序升级。

自动化

那么问题又来了,怎么将上述的更新流程自动化运行呢?有两个方式能够达到:

  1. 将容器更新、启停、切换等操做封装到一个单一的脚本中,这个脚本能够加入到传统的上线流程(注:新代码拉取,自动测试,自动部署的流程,做者称之为deployment pipeline)以后执行;
  2. 另外一种方式是,使用相似Consul或者etcd等的发现服务来管理容器的更新,启停,与发现;这会更加“高大上”。

因此,使用Docker在生产环境中部署服务不像你想象中那么容易。我推荐你们试试上面所说的方法;同时分享你本身的实践经验给你们,这会帮助你们一同使用Docker。Docker仍是个很年轻的产品,同时又是个很是热门的产品,它确定会在将来不断的演化升级。

免费提供最新Linux技术教程书籍,为开源技术爱好者努力作得更多更好:http://www.linuxprobe.com/

相关文章
相关标签/搜索