【问题标题】:Can Docker images be "built" ("compiled") to not require Docker?可以“构建”(“编译”)Docker 映像以不需要 Docker 吗?
【发布时间】:2018-04-29 03:00:45
【问题描述】:

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

主要问题

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

为了在生产环境中运行这个镜像(因此为了在生产环境中运行我的应用程序),生产服务器必须安装 Docker。这感觉像是违反The Twelve-Factor App 设计。特别是当您考虑Port Binding 的信条时:

十二要素应用完全独立

就像一个应用不应该依赖 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 已更新
  • cURL 已安装
  • 已安装所有必需的 PHP 扩展
  • 安装了几个 GNU 库
  • 等

我花了 小时 试图让这段代码运行 - 它是 我 编写的代码

所有这些问题让我想起了The Twelve-Factor App 设计。所以我跳到网站上,想了想弄清楚我做错了什么。

注意:我不只是单独开发,然后直接部署到生产环境。我实际上在 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
  • Laravel
  • NodeJS
  • NPM
  • 吞咽
  • 引导程序
  • VueJS
  • (可能还有很多我现在想不出来的事情)

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

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

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

【问题讨论】:

  • 我认为不可能将 docker 图像转换为二进制文件,但在某些时候它必须依赖 apache 或 nginx 才能提供内容,否则有什么意义。顺便说一句,它很容易学习
  • 其实web应用不需要需要依赖Apache或者nginx来提供内容。 Apache 和 nginx 所做的只是解析 HTTP 请求并自动为您处理一些错误情况。如果您的应用能够解释 HTTP 请求,那么您的应用可以充当自己的 HTTP 服务器(直接绑定到端口 80)。这就是 NodeJS Web 应用程序的工作量。然后将 Apache 和 nginx 用作负载均衡等的代理层。

标签: php laravel docker docker-compose 12factor


【解决方案1】:

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

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

【讨论】:

  • 对于今天出现的两个答案中的哪一个我应该接受,我实际上有点纠结。这个答案提供了更多的技术细节,实际上解释了我如何在理论上完成我想要的(如果我找到一个可以作为容器运行时的库,那么我可以很容易地将它编译成一个独立的可执行文件)。也就是说,@OphirYoktan 的回答可能被认为是更好的做法,因为他指出单个依赖项 (Docker) 优于 40 个依赖项,这很像 JVM 允许在任何地方构建一次部署,Docker 也是如此。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 2020-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    • 2018-01-01
    相关资源
    最近更新 更多