一尘不染

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

docker

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

我最近通过dockerized了与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定义了需要在容器内执行的命令(如docker-compose exec php composer installPHP),则Docker会告知该容器尚不存在(因为现有容器是在先前的发行文件夹中创建的)。
  • 如果docker-compose up -d在Capistrano部署过程中执行了命令,由于端口冲突(以前的容器仍然存在),我会遇到一些错误。

您是否有解决此问题的想法?我应该离开Capistrano并做一些不同的事情吗?

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


阅读 302

收藏
2020-06-17

共1个答案

一尘不染

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

基本上,您这样做时,在运行cap部署时

  • 构建应用程序(基于您在主机上获得的当前基础)-甚至可能包括gulp / grunt / build任务
  • 然后使用“卷挂载”将其“打包”到映像中
  • 在此期间,您开始/更换容器

您这样做是为了实现“近乎”零停机时间的部署。

如果您真的很在意停机时间并非常在乎您的部署过程,那么应该使用正确的管道实现

  • 包装/ ci
  • 部署/分配

我认为capistrano不能/不应成为您在此策略期间可以使用的工具之一。Capistrano旨在使用ssh和git作为传输直接在服务器上部署应用程序。顶住恕我直言,使用cap在目标服务器上构建整个映像,然后将其作为容器启动。

包装/建筑

使用诸如jenkins / bamboo / gocd之类的CI /
CD服务器为您的应用程序构建一个发行映像。假设仅根据“发布”对应用进行了自定义,假设您将数据库和应用作为容器/服务,则应用将包含您的源代码,并且在发布期间会定期更改。

因此,通过CD /
CI流程可在CI服务器上离线构建新的应用程序映像(发行版)。使用以下命令将应用程序的源代码打包,将其打包到图像中COPY,然后使用任何RUN语句来编译您的资产(npm
/ gulp / grunt等等)。所有这些都不在生产服务器上发生,而是在CI / CD代理上发生。鼓励对苗条图像使用多阶段构建。

然后,您推送此发布映像,让我们将该映像作为新的“版本”
调用yourregistry.com/yourapp到您的私有注册表中。

部署

停机(轻松)

要在停机期间部署到生产或登台服务器中,只需执行以下操作docker-composer pull && docker-composer up-这将提取较新的映像,然后在堆栈中启动它-应用已升级。在发布阶段使用带标签的图像将需要更改docker-compose.yml

该服务器当然应该能够从您的专用存储库中提取。

无需停机(更多精力)

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

我们正在使用随机端口来避免在部署“第二个”系统期间发生冲突,这涵盖了您提到的问题之一。

重新部署时,您仅会基于新的应用程序映像(除了旧的)启动一个“新”容器,它会获得一个新的随机端口12312-如果您愿意,请直接运行集成测试12312(不要使用代理)。如果您满意并满意,请重新配置代理以立即转发到12312-然后删除旧容器(21231)。

如果您想自动化代理重新配置( 详细信息
不在此问题范围之内),则可以使用服务发现和注册器,该注册器使随机端口更加实用,并易于重新配置代理,请将其设为nginx /
haproxy运行时。例如,将使用工具。

2020-06-17