Минимизируйте размер контейнера Docker, созданного с помощью `dockertools.buildImage` от Nix.

Я упаковываю приложение Python в докер с помощью nix dockerTools, и все хорошо, кроме размера изображения. Сам Python весит около 40 Мб, а если добавить numpy и pandas, получится несколько сотен мегабайт, а код приложения всего ~100 КБ.

Единственное решение, которое я вижу, это упаковать зависимости в отдельный образ, а затем унаследовать от него основной, это не исправит размер, но, по крайней мере, мне не нужно будет передавать огромные изображения при каждом коммите. Также я не знаю, как это сделать, должен ли я использовать какой-либо образ с nix или создать среду с pythonPackages.buildEnv и прикрепить к нему свое приложение?

Было бы здорово иметь какое-то универсальное решение, но было бы хорошо, если бы оно было специфичным для Python. Даже если у вас есть несовершенное решение, пожалуйста, поделитесь.

Хорошо, с атрибутом fromImage для buildImage я разделил один огромный слой на огромный уровень зависимостей и небольшой слой кода приложения. Интересно, есть ли способ переместить этот толстый слой зависимостей в отдельный образ, чтобы я мог поделиться им с другими моими проектами?


person cvb    schedule 09.06.2017    source источник


Ответы (2)


Нет необходимости упаковывать свои зависимости в отдельный образ и наследовать его, хотя это и не навредит.

Все, что вам нужно сделать, это убедиться, что вы добавили код своего приложения в качестве одного из последних шагов в Dockerfile. Каждая команда будет иметь свой собственный уровень, поэтому, если вы измените только код своего приложения, все слои выше этого изменения можно будет использовать из кеша.

Пример из Образы и слои Docker:

Докерфайл

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

содержит четыре отдельных слоя. Если вы измените только последнюю строку, необходимо будет перенести только этот слой и все слои ниже него. При нажатии или вытягивании вы увидите 4b0ba2c4050a: Already exists рядом со слоями, используемыми из кеша. Следуя этому подходу, вы не получите изображение меньшего размера, но, как вы говорите, вам не нужно извлекать большие изображения при каждом изменении.

person Hendrikvh    schedule 09.06.2017

Немного погуглив и прочитав dockerTools код, я остановился на таком решении:

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

Это создаст двухслойный образ докера, один из которых будет зависимостями, а другой — приложением. Также кажется, что значение для fromImage может быть результатом pullImage, которое должно дать вам тот же результат (если я правильно понял код), но я не смог это проверить.

person cvb    schedule 13.06.2017