我对 Docker 进行实验和开发的经验非常少,而在暂存和部署方面,我对 Docker 的经验为零——所以请原谅任何听起来幼稚的事情。
主要问题
假设我有一个 Docker 映像(甚至是一个docker-compose.yml
由多个映像和服务组成的文件),它在运行时为我的应用程序设置环境并运行我的应用程序 - 允许在公共开放端口上进行连接并响应请求。
为了在生产中运行这个镜像(因此为了在生产中运行我的应用程序),生产服务器必须安装 Docker。这感觉像是违反了十二要素应用程序的设计。特别是当您考虑端口绑定原则时:
十二因素应用程序是完全独立的
就像一个应用程序不应该依赖 Apache 或 nginx 来安装一样,一个应用程序也不应该依赖 Docker 来安装吗?
这让我想知道是否有办法将 Docker 运行时和映像“打包”、“构建”或以其他方式“编译”成可执行二进制文件。可以部署到任何服务器并作为单个进程运行而无需先安装 Docker 的东西。
现在,我可能只是在想这完全错误的。出于这个原因,我已经详细说明了我在下面遇到的担忧和问题
是什么引起了这一切
我有一个以前使用Cloud9开发的 Web 应用程序项目。当我将此项目推送到生产环境时,我通过 SSH 手动登录到生产服务器并执行git pull
、composer update
、npm install
和gulp
. 我有点麻烦,但对于我工作的非常小的规模来说,这已经足够了,这比通过 FTP 上传我的所有依赖项要好得多。
但是,我偶尔会遇到外部依赖项的挑战。有些东西在开发中运行良好,然后当我将它推送到生产环境时,我意识到生产服务器有一个过时的 MySQL 版本。或者生产服务器上安装的 pngquant 版本有 bug。或者服务器上的 nginx 配置与开发中的 nginx 配置不完全匹配,并且在路由格式错误的请求时会导致一些边缘情况。
今天,当我尝试在CodeAnywhere而不是 Cloud9 中加载我的项目时,所有这些问题都立即出现了。我必须确保:
- PHP 版本已更新
- NodeJS 已更新
- NPM 已更新
- 卷曲已安装
- 安装了所有必需的 PHP 扩展
- 安装了几个 GNU 库
- ETC
我花了几个小时试图让这段代码运行——这是我写的代码
遇到所有这些问题让我想起了十二要素应用程序设计。所以我跳到网站上,想了想弄清楚我做错了什么。
注意:我不只是单独开发,然后直接部署到生产环境。我实际上在 BitBucket 中设置了这个项目,我使用票务系统来跟踪更改,为每个票创建一个分支,并在合并到 master 之前在暂存环境中签出分支。因此,我创建了一个非常强大的系统来管理更改,以避免错误进入生产环境并允许敏捷开发。但是,当涉及到在暂存或生产中检查分支时,它是相同的手动废话:git pull
, composer update
, npm install
, gulp
.
我喜欢 Docker 的地方
在源代码控制的配置文件中定义我的工作环境的能力将消除我的大部分问题。我再也不需要确保 PHP 是最新的、确保 NodeJS 是最新的、确保安装了 cURL 等。如果 Docker 映像具有所有依赖项,那么在部署到暂存或生产时它仍然具有这些依赖项. 各个发展阶段之间的环境一致性将使我的生活更轻松。
另外,我还没有玩过这么高级的东西,但我知道使用 Docker 很容易设置自动部署。如果我可以单击 BitBucket 中的一个分支,然后单击“发送到暂存”,一分钟后将其部署并准备好进行测试——这将每周为我节省数小时的时间。如果我可以类似地在将代码合并到 master 时将代码自动部署到生产中,那不仅可以节省我的时间,而且可以避免完成的功能在 BitBucket 中停滞不前并且永远不会出现在客户面前的风险。
最后,这可能最终成为一个有争议的问题,我理解 Docker 使绿色/蓝色部署变得更加容易。目前,当我将新更改推送到生产环境时,生产服务器会短暂脱机。通常只持续 15-20 秒,但一次是整整一个小时。在这 15-20 秒的窗口中,我正在运行composer update
、npm install
和gulp
。前两个命令通常不需要做任何事情(因为我的依赖项不经常更改)并且gulp
通常在 15 秒内完成。但是,当依赖项更改或出现较大问题(例如需要升级 MySQL)时,站点可能会关闭一小时。如果我可以缓慢而平静地部署到辅助生产服务器,然后在我验证它工作正常时在几毫秒内翻转开关,这将意味着更少的停机时间和更多的客户满意度。
当然最后一个可能是一个有争议的点,因为我目前没有使用“构建”步骤(十二因素应用程序的另一部分),所有这些步骤都应该是“构建”阶段的一部分——不是“部署”阶段。
我不喜欢 Docker 的地方
它又是一种学习工具。为了理解和开发我的应用程序,您已经需要了解:
- PHP
- 作曲家
- Symfony
- 拉拉维尔
- 节点JS
- 新PM
- 吞咽
- 引导程序
- VueJS
- (可能还有很多我现在想不起来的事情)
将“Docker”添加到该列表仅意味着如果我将这个项目交给另一个开发人员,那么培训某人会变得更加困难。我想要更少的依赖,而不是更多。
此外,我所知道的任何操作系统都没有默认 Docker。因此,它不像 cURL,虽然它在技术上是第三方依赖项,但您通常可以期望人们拥有它。相反,它是一个必须单独安装的整体野兽。
前一个问题我无法真正规避。如果我选择使用 Docker,这意味着在我的工具箱中为这个应用程序添加了一个工具。但是,如果 Docker 映像可以以某种方式编译为独立的二进制文件,则可以避免后一个问题。