2

我对 Docker 进行实验和开发的经验非常少,而在暂存和部署方面,我对 Docker 的经验为零——所以请原谅任何听起来幼稚的事情。

主要问题

假设我有一个 Docker 映像(甚至是一个docker-compose.yml由多个映像和服务组成的文件),它在运行时为我的应用程序设置环境并运行我的应用程序 - 允许在公共开放端口上进行连接并响应请求。

为了在生产中运行这个镜像(因此为了在生产中运行我的应用程序),生产服务器必须安装 Docker。这感觉像是违反了十二要素应用程序的设计。特别是当您考虑端口绑定原则时:

十二因素应用程序是完全独立的

就像一个应用程序不应该依赖 Apache 或 nginx 来安装一样,一个应用程序也不应该依赖 Docker 来安装吗?

这让我想知道是否有办法将 Docker 运行时和映像“打包”、“构建”或以其他方式“编译”成可执行二进制文件。可以部署到任何服务器并作为单个进程运行而无需先安装 Docker 的东西。

现在,我可能只是在想这完全错误的。出于这个原因,我已经详细说明了我在下面遇到的担忧和问题

是什么引起了这一切

我有一个以前使用Cloud9开发的 Web 应用程序项目。当我将此项目推送到生产环境时,我通过 SSH 手动登录到生产服务器并执行git pullcomposer updatenpm installgulp. 我有点麻烦,但对于我工作的非常小的规模来说,这已经足够了,这比通过 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 updatenpm installgulp。前两个命令通常不需要做任何事情(因为我的依赖项不经常更改)并且gulp通常在 15 秒内完成。但是,当依赖项更改或出现较大问题(例如需要升级 MySQL)时,站点可能会关闭一小时。如果我可以缓慢而平静地部署到辅助生产服务器,然后在我验证它工作正常时在几毫秒内翻转开关,这将意味着更少的停机时间和更多的客户满意度。

当然最后一个可能是一个有争议的点,因为我目前没有使用“构建”步骤(十二因素应用程序的另一部分),所有这些步骤都应该是“构建”阶段的一部分——不是“部署”阶段。

我不喜欢 Docker 的地方

它又是一种学习工具。为了理解和开发我的应用程序,您已经需要了解:

  • PHP
  • 作曲家
  • Symfony
  • 拉拉维尔
  • 节点JS
  • 新PM
  • 吞咽
  • 引导程序
  • VueJS
  • (可能还有很多我现在想不起来的事情)

将“Docker”添加到该列表仅意味着如果我将这个项目交给另一个开发人员,那么培训某人会变得更加困难。我想要更少的依赖,而不是更多。

此外,我所知道的任何操作系统都没有默认 Docker。因此,它不像 cURL,虽然它在技术上是第三方依赖项,但您通常可以期望人们拥有它。相反,它是一个必须单独安装的整体野兽。

前一个问题我无法真正规避。如果我选择使用 Docker,这意味着在我的工具箱中为这个应用程序添加了一个工具。但是,如果 Docker 映像可以以某种方式编译为独立的二进制文件,则可以避免后一个问题。

4

2 回答 2

2

严格来说,你可以在没有 docker 的情况下从 docker 镜像运行容器。Docker 镜像是一种众所周知的格式。有关此规范的更多详细信息,请参阅https://github.com/opencontainers/image-spec。OCI 图像的运行时有多种实现。Docker 本身实际上并不运行容器,该任务已外包给 containerd。

然而,镜像附带一个文件系统(也称为一堆 tar 文件),但容器也期望命名空间来隔离应用程序。您需要某种运行时来实现这一点。容器不仅仅是一种打包应用程序的方法,也是一种单独运行它们的方法,尝试将它们分开将是更多的工作,并创造出比 docker 本身更大的学习内容。

于 2018-10-12T12:58:17.203 回答
1

Docker 映像确实需要在机器上安装 docker,但与设置您提到的所有其他依赖项相比,这是一个小得多的问题。

虽然可能可以创建某种自包含的 docker 映像,但它可能不如 docker 映像那么可移植,因为二进制文件将依赖于操作系统。

还要考虑,如果您使用云提供商,他们提供“直接在云上”部署 docker 映像的能力——也就是说,您不必管理底层服务器

于 2018-10-12T08:08:15.387 回答