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

我不确定我的问题是否相关,因为我可能会尝试混合不应混合的工具(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 (取决于您的选择)
  • ——

    https://stackoverflow.com/questions/39457603/

    相关文章:

    python - 如何使用 pip 安装本地软件包作为 docker 构建的一部分?

    docker - 什么是容器 list ?

    docker - 如何将 Docker 容器中的目录挂载到主机?

    docker - 扩展本地 Dockerfile

    docker - Docker 容器中的 asp.net 核心与 Azure App 服务

    ruby-on-rails - 无法运行 rake db :create in Dockerfile

    docker - 拉取访问被拒绝的存储库不存在或可能需要 docker login

    docker - 在 docker 中标记图像

    docker - 多个 Docker 容器可以使用相同的主机/端口运行吗?

    docker - Jenkins + Docker : How to control docker