阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

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

72次阅读
没有评论

共计 2810 个字符,预计需要花费 8 分钟才能阅读完成。

导读 Docker 现在越来越流行,但是真正在生产环境部署 Docker 还是个比较新的概念,还没有一个标准的流程。作者是 ROR 的程序员,作者结合平时的部署经验,联系 Docker 的特点,向大家分享了其在生产环境使用 Docker 部署应用程序的一个实践。

Docker 是现在开发应用程序的不错选择;因为对于一个研发组来说,部署一个应用再也不用像以前那样繁琐的修改、设置配置文件了;因为对于 Docker 来说它“屏蔽”了应用程序的运行环境,不管你使用 Mac、Linux 还是 Windows 都能用相同的方式运行。

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

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

标准

在实际操作之前,我们列举生产环境部署应用的标准:

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

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

$ 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 还是个很年轻的产品,同时又是个非常热门的产品,它肯定会在未来不断的演化升级。

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-07-24发表,共计2810字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中