如何整合Capistrano与Docker进行部署?

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

我最近dockerized与Capistrano部署的应用程序。 Docker compose用于开发环境和登台环境。

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

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

Docker Compose文件创build了所有必要的容器(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定义了需要在容器中执行的命令(比如docker-compose exec php composer install器),Docker会告诉容器不存在(因为现有的容器是在以前的发布文件夹中创build的)。
  • 如果在Capistrano部署过程中执行docker-compose up -d命令,由于端口冲突(以前的容器仍然存在),我会收到一些错误。

你有关于如何解决这个问题的想法? 我应该离开Capistrano做一些不同的事吗?

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

据我了解,你在主机上使用capistrano来重新部署整个应用程序堆栈,意味着容器。 所以你正在使用capistrano来编排build设,容器创build和部署。

虽然你这样做,你基本上,当运行帽部署

  • build立应用程序(根据您在主机上的当前基地) – 可能甚至包括吞咽/咕噜声/构build任务
  • 然后使用“卷装”将其“打包”到容器中
  • 在此期间您开始/更换容器

您这样做是为了获得“接近零”的停机时间部署。

如果你真的关心停机时间,并关心正式的部署过程,那么你应该正确地使用适当的pipe道实现

  • 包装/ ci
  • 部署/分发

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

包装/build筑

可以使用像jenkins /竹/ gocd这样的CI / CD服务器为您的应用程序构build发布映像。 假设只有应用程序是根据“发布”来定制的,可以说你有db和app作为容器/服务,应用程序将包含你的源代码,并且在发布过程中会定期更改。

因此,它是一个在您的CI服务器上异地构build新的应用程序映像(发行版)的CD / CI过程。 拉你的应用程序的源代码打包到你的图像使用COPY ,然后任何RUN语句来编译你的资产(npm / gulp / grunt)。 这一切都不是发生在生产服务器上,而是发生在CI / CD代理上。

然后你推送这个release-image,让我们把这个图像yourregistry.com/yourapp作为一个新的“版本”部署到你的私人registry中。

部署

与停机时间(简单)

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

服务器当然可以从你的私有存储库中取出。

宕机(更努力)

实现零停机时间部署,您应该使用蓝绿色的部署概念 。 因此,你添加一个代理到你的设置,不再公开应用程序的公共端口,而是使用这个代理公共端口。 您当前的实时系统可能运行在随机端口21231上,代理从443转发到21231。

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

重新部署时,只会启动一个基于新的应用程序映像的“新”容器(旧的),它会得到一个新的随机端口12312 – 如果你喜欢,直接运行你的集成testing12312(不要使用代理)。 如果你已经完成并且快乐,重新configuration代理现在转发到12312 – 然后删除旧的容器(21231)。

如果你想自动执行代理重新configuration,这个问题已经超出了这个问题的范围,那么你可以使用服务发现和注册器,这使得随机端口变得更加实用,而且很容易重新configuration你的代理,让它成为nginx / haproxy正在运行。 工具将是,例如。

  • 领事
  • 在代理上的consul watch + consul-template或tiller更新proxy-config
  • 使用service-configuration.json进行集中注册或代理客户端模式的注册人(取决于您的select)

我不认为Capistrano是工作的正确工具。 最近在Capistrano的SSHKit公关中进行了讨论。

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

@EugenMayer更好地解释了使用Docker的“正常”方式。