我不确定我的问题是否相关,因为我可能会尝试混合不应混合的工具(Capistrano 和 Docker)。
我最近对一个使用 Capistrano 部署的应用程序进行了docker化。 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
符号链接(symbolic link)将指向
releases
的新目录目录:
如 deploy.rb
定义需要在容器内执行的命令(如 docker-compose exec php composer install
对于 PHP),Docker 告诉容器还不存在(因为现有的容器是在以前的版本文件夹中创建的)。 如果 docker-compose up -d
命令在 Capistrano 部署过程中执行,由于端口冲突(以前的容器仍然存在)而出现一些错误。 你对如何解决这个问题有什么想法吗?我应该离开 Capistrano 并做一些不同的事情吗?
这个想法是保持 Capistrano 提供的(接近)零停机时间部署和 Docker 容器的灵 active (例如,为同一服务器上的各种应用程序提供多个 PHP 版本)。
据我了解,您在主机上使用 capistrano 来重新部署整个应用程序堆栈,这意味着容器。因此,您正在使用 capistrano 来协调构建、容器创建和部署。
当您这样做时,您基本上是在运行 cap deploy 时
构建应用程序(基于您在主机上拉取的当前基础)- 甚至可能包括 gulp/grunt/build 任务 然后使用“卷安装”将其“打包”到您的图像中 在此期间,您启动/更换容器 您这样做是为了获得“几乎”零停机时间的部署。
如果你真的非常关心停机时间和正式化你的部署过程,你应该通过使用适当的管道实现来正确地实现
包装/ci 部署/分发我不认为 capistrano 可以/不应该是您在此策略中可以使用的工具之一。 Capistrano 旨在使用 ssh 和 git 作为传输直接在服务器上部署应用程序。使用 cap 在目标服务器上构建整个图像,然后将它们作为容器启动,真的是过头了,恕我直言。
包装/建筑
要么使用像 jenkins/bamboo/gocd 这样的 CI/CD 服务器为您的应用程序构建发布镜像。假设仅根据“发布”自定义应用程序,假设您将 db 和应用程序作为容器/服务,应用程序将包含您的源代码,并且会在发布期间定期更改..
因此,它是一个 CD/CI 过程,用于在您的 CI 服务器上异地构建新的应用程序镜像(发布)。使用
COPY
提取应用程序的源代码并将其打包到您的镜像中然后是任何
RUN
编译 Assets 的语句( npm/gulp/grunt )。这一切都不是发生在生产服务器上,而是发生在 CI/CD 代理上。鼓励对纤薄图像使用多阶段构建。
然后你推送这个发布图像,让我们调用这个图像
yourregistry.com/yourapp
进入您的 private registry作为用于部署的新“版本”。
部署
有停机时间(简单)
要在停机的情况下部署到您的生产或临时服务器,您只需执行
docker-composer pull && docker-composer up
- 这将拉取较新的图像,然后在您的堆栈中启动它 - 您的应用程序已升级。在发布阶段使用标记图像需要更改 docker-compose.yml
服务器当然应该能够从您的私有(private)存储库中提取。
没有停机时间(更多的努力)
要实现零停机部署,您应该使用 blue-green deployment concept .因此,您将代理添加到您的设置中,并且不再从应用程序公开公共(public)端口,而是使用此代理公共(public)端口。您当前的实时系统可能在随机端口 21231 上运行,代理正在从 443 转发到 21231。
我们使用随机端口来避免部署“第二个”系统时的冲突,涵盖了您提到的问题之一。
重新部署时,除了(旧的)之外,您只会基于新的应用程序镜像启动一个"new"容器,它会获得一个新的随机端口 12312 - 如果您愿意,可以直接再次运行集成测试 12312(不要使用代理)。如果您已完成并满意,请重新配置代理以现在转发到 12312 - 然后移除旧容器 (21231)。
如果您想自动化代理重新配置,这在细节上超出了这个问题的范围,您可以使用服务发现和注册器,这使随机端口更加实用,并且可以轻松地重新配置您的代理,让它成为 nginx/haproxy 在它们运行时。例如,工具将是。
领事 consul watch
+ consul-template
或 tiller在代理上更新代理配置 Registator集中注册或consul agent client mode与 service-configuration.json (取决于您的选择) ——