最小化 docker 使用 Nix 的 `dockertools.buildImage` 构建的容器大小

Minimize docker container size built with Nix's `dockertools.buildImage`

我正在使用 nix 的 dockerTools 将 python 应用程序打包到 docker 中,除了图像大小外,一切都很好。 Python本身大约40Mb,加上numpypandas就几百兆,而应用程序代码只有~100Kb。

我看到的唯一解决方案是将依赖项打包到单独的图像中,然后从中继承主图像,它不会固定大小,但至少我不需要在每次提交时传输巨大的图像。我也不知道该怎么做,我应该使用带有 nix 的图像,还是使用 pythonPackages.buildEnv 构建环境并将我的应用程序附加到它?

最好有一些通用的解决方案,但 python 具体的解决方案会更好。即使您有不完美的解决方案,也请分享。

好的,使用 fromImage attr for buildImage 我将一个巨大的层拆分为巨大的依赖层和小的应用程序代码层。 我想知道是否有任何方法可以将这个胖依赖层移动到单独的图像中,以便我可以在我的其他项目中共享它?

没有必要将您的依赖项打包到单独的映像中并继承它,尽管那样不会造成伤害。

您需要做的就是确保将应用程序代码添加为 Dockerfile 中的最后一步。每个命令都有自己的层,因此如果您只更改应用程序代码,则可以从缓存中使用该更改之上的所有层。

Docker Images and Layers 文档中的示例:

dockerfile

FROM ubuntu:15.10
COPY . /app
RUN make /app
CMD python /app/app.py

包含四个不同的层。如果只修改最后一行,则只需要传输该层及其下的所有层。推或拉时,您会在缓存中使用的图层旁边看到 4b0ba2c4050a: Already exists。 按照这种方法,您最终不会得到较小的图像,但正如您所说,您不必在每次更改时都拉出大图像。

谷歌搜索了一下并阅读了 dockerTools 代码后,我以这个解决方案结束:

let
  deps = pkgs.dockerTools.buildImage {
    name = "deps";
    content = [ list of all deps here ];
};
in pkgs.dockertools.buildImage {
  name = "app";
  fromImage = deps;
}

这将构建两层 docker 图像,其中一层是依赖项,另一层是应用程序。 fromImage 的值似乎也可能是 pullImage 的结果,它应该给你相同的结果(如果我理解正确的代码),但我无法检查它。