如何整合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的“正常”方式。