如何将Capistrano与Docker集成进行部署?

时间:2016-09-12 19:39:07

标签: docker deployment docker-compose capistrano3

我不确定我的问题是否相关,因为我可能会尝试混合不应混合的工具(Capistrano和Docker)。

我最近将与Capistrano一起部署的应用程序停靠。 Docker compose用于开发和登台环境。

这就是我的项目的样子(应用程序文件未显示):

Capfile
docker-compose.yml
docker-compose.staging.yml
config/
    deploy.rb
    deploy
        staging.rb

Docker Compose文件创建了所有必要的容器(Nginx,PHP,MongoDB,Elasticsearch等),以便在开发或登台环境中运行应用程序(因此在docker-compose.staging.yml中定义了一些特定参数)。

使用此命令将应用程序部署到登台环境:

cap staging deploy

服务器上的文件夹架构是Capistrano:

current
releases
    20160912150720
    20160912151003
    20160912153905
shared

以下命令已在登台服务器的current目录中运行,以实例化运行该应用程序所需的所有容器:

docker-compose -f docker-compose.yml -f docker-compose.staging.yml up -d

到目前为止一切顺利。在下一次部署时,事情变得更加复杂:current符号链接将指向releases目录的新目录:

  • 如果deploy.rb定义了需要在容器内执行的命令(例如PHP的docker-compose exec php composer install),Docker告诉容器还不存在(因为现有容器是在以前的发布文件夹)。
  • 如果在Capistrano部署过程中执行docker-compose up -d命令,由于端口冲突(以前的容器仍然存在),我会收到一些错误。

您对如何解决此问题有所了解吗?我应该离开卡皮斯特拉诺并做些不同的事吗?

我们的想法是保持Capistrano提供的(近乎)零停机时间部署以及Docker容器的灵活性(例如,为同一服务器上的各种应用程序提供多个PHP版本)。

2 个答案:

答案 0 :(得分:18)

据我所知,你在主机上使用capistrano,重新部署整个应用程序堆栈,意味着容器。因此,您正在使用capistrano来协调构建,容器创建以及部署。

当你这样做时,基本上,当你运行cap deploy

  • 构建应用程序(基于您在主机上提取的当前基础) - 可能甚至包括gulp / grunt / build任务
  • 然后使用“volume mounts”将其“打包”到您的容器中
  • 在此期间启动/更换容器

您这样做是为了实现“几乎”零停机部署。

如果您真的非常关心停机时间以及将部署过程正式化,那么您应该通过使用适当的管道实现来做到这一点

  • packaging / ci
  • 部署/分发

我不认为capistrano可以/应该是您在此策略中可以使用的工具之一。 Capistrano用于使用ssh和git作为传输直接在服务器上部署应用程序。使用上限在目标服务器上构建整个图像,然后启动那些作为容器,真的超过顶部,恕我直言。

包装/建筑

使用像jenkins / bamboo / gocd这样的CI / CD服务器为您的应用程序构建一个发布图像。假设只有应用程序是根据“发布”自定义的,假设你有db和app作为容器/服务,app将包含你的源代码,并会在发布期间定期更改..

因此,它是一个CD / CI流程,用于在CI服务器上异地构建新的应用程序映像(发布)。拉动应用程序的源代码,使用COPY将其打包到图像中,然后使用任何RUN语句编译资产(npm / gulp / grunt等)。这一切都不会发生在生产服务器上,而是发生在CI / CD代理上。

然后推送此版本图片,我们将此图片yourregistry.com/yourapp称为private registry作为新版本的“{3}”进行部署。

部署

停机时间(简单)

要在停机时部署到您的生产或登台服务器,您只需执行docker-composer stop && docker-composer up - 这将自动拉出较新的图像,然后在您的堆栈中启动它 - 您的应用程序已升级

服务器当然应该可以从您的私人存储库中提取。

停机时间(更多努力)

实现零停机部署,您应该使用blue-green deployment concept。因此,您将代理添加到您的设置中,不再从应用程序公开公共端口,而是使用此代理公共端口。您当前的实时系统可能在随机端口21231上运行,代理从443转发到21231。

我们正在使用随机端口来避免在部署“第二”系统时发生冲突,包括您提到的问题之一。

重新部署时,你只会基于新的app-image启动一个“新”容器(对旧版本),它会获得一个新的随机端口12312 - 如果你愿意,可以直接运行你的集成测试12312 (不要使用代理)。如果您已经完成并且感到满意,请将代理重新配置为现在转发到12312 - 然后删除旧容器(21231)。

如果您希望自动执行代理重新配置,详细超出此问题的范围,您可以使用服务发现和registrator使随机端口更加实用并使其成为可能很容易重新配置代理,让它们在运行时成为nginx / haproxy。例如,工具就是。

答案 1 :(得分:4)

我不认为Capistrano是这项工作的正确工具。最近在SSHKit的PR中对此进行了讨论,这是Capistrano的基础。

https://github.com/capistrano/sshkit/pull/368

@EugenMayer更好地解释了#34;正常"使用Docker的方式。