【问题标题】:How to remove development dependencies in production docker images如何删除生产 docker 镜像中的开发依赖项
【发布时间】:2017-02-09 17:14:40
【问题描述】:

在将 dockerized node.js 运送到生产环境时, 发布包含开发依赖项的图像是否正确?

我不是在说开发依赖 不是packages.json中列出的devDependencies,我的意思是gcc、python、node-gyp、其他一些*-dev包,包含一堆头文件、静态库。 都需要编译一些节点依赖(比如node-sass)

一个想法可以是两阶段构建,一个包含所有 *-dev 依赖项的映像,在其中构建内容,然后将结果导出到另一个仅包含二进制文件的新映像。

  • 优点:最终的“生产”图像很小
  • 缺点:不是标准的图像构建方式

一般来说,我想在 docker 镜像中分发的任何已编译软件都不应包含用于构建二进制文件的编译器、头文件和工具。

【问题讨论】:

  • '发送包含开发依赖项的图像是否正确?我不是在谈论开发依赖关系,哈哈
  • 这就是为什么括号解释了我所指的开发依赖项,但是是的,哈哈
  • 这个问题太笼统了。对于 C++ 项目。干净的图像将仅包含 *.so 供您的主程序使用。您可以通过 apt install libxxx 而不是 apt install ibxxx-dev 来执行此操作。或者,您可以使用ldd 查找所有依赖项,将主程序、所需的*.so、资源文件复制到现有的官方Linux 映像上。对于python,没有干净的方法可以做到这一点。 Python 依赖关系太复杂了。对于新时代的编程语言,例如 Golang 或 Rust,捆绑要容易得多,因为它们默认是静态链接的。而且不会有依赖地狱。

标签: node.js docker production node-gyp


【解决方案1】:

如果您希望最终图像中不包含某些内容,则必须仅在一层(一个 RUN 语句)中执行所有相关命令。

类似下面的东西(伪代码):

RUN install dev-dependencies && build your-project && uninstall dev-dependencies

只为 RUN 语句创建一个层,它不会包含开发依赖项。

【讨论】:

    【解决方案2】:

    如果删除依赖项,图像不会更小,因为旧层包含它们。

    使用 Docker 1.13 尝试新的(实验性)--squash 选项和 docker-build。

    【讨论】:

    • 没错,我不能只删除后面层的文件,这就是为什么一个想法可能是使用一个图像来编译,另一个图像来打包二进制文件,除了,现在我应该有两个单独的,不可继承的 Dockerfiles
    【解决方案3】:

    OP 问题的答案取决于 OP/他的公司为生产需要维护了多少图像。

    可能的策略很少:

    1. 如果维护的镜像数量中低,系统架构不是很复杂,不一次使用几十个镜像,那么最简单和最容易维护的解决方案就是最好的解决方案。您可以使用 1 个单一构建来接近它。或者,如果您想使用编译后的源代码作为可以承载不同内容的容器的基础,则需要 2 步构建(在这种情况下,甚至可以在 docker-compose up(系统启动)期间完成第 2 阶段)。

    2. 如果有必要保持图像苗条/有许多正在运行的容器使用相同的图像/编译文件的大小很大,您可以删除仅开发依赖项(如其他答案所建议的那样)。这将增加构建过程的时间跨度,但会导致图像更小。

    3. 第三种方法完全不同 - 如果有编译过程,请使用 CI 管道在单独的容器(CI 运行程序进程)中独立编译资产并提供版本化工件 - 您可以在生产构建中使用它(甚至存储它在某个地方,在 S3/CDN/private 上,可访问部署存储),然后从那里获取它,或者只使用那里托管的文件(在 CDN 的情况下)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-26
      • 2014-02-19
      • 2021-09-15
      • 1970-01-01
      • 1970-01-01
      • 2016-08-03
      • 2017-11-15
      • 2018-04-28
      相关资源
      最近更新 更多