Dockerfile — Понимание Слоев Docker

  • Автор темы Sandris
  • Обновлено
  • 22, Oct 2024
  • #1

У нас есть следующий блок в нашем

RUN
:

RUN

Мне сказали, что мы должны объединить эти

RUN yum -y update \

&& yum -y install epel-release \

&& yum -y groupinstall "Development Tools" \

&& yum -y install python-pip git mysql-devel libxml2-devel libxslt-devel python-devel openldap-devel libffi-devel openssl-devel
commands to cut down on created docker layers:

RUN

Я новичок в докере и не уверен, что полностью понимаю различия между этими двумя версиями указания нескольких команд RUN. Когда бы можно было объединиться

RUN yum -y update
RUN yum -y install epel-release
RUN yum -y groupinstall "Development Tools"
RUN yum -y install python-pip git mysql-devel libxml2-devel libxslt-devel python-devel openldap-devel libffi-devel openssl-devel
commands into a single one and when it makes sense to have multiple
Dockerfile
команды?

#докер #dockerfile

Sandris


Рег
31 Jul, 2006

Тем
76

Постов
207

Баллов
587
  • 25, Oct 2024
  • #2

Образ Docker на самом деле представляет собой связанный список слоев файловой системы. Каждая инструкция в Докерфайл создает уровень файловой системы, описывающий различия в файловой системе до и после выполнения соответствующей инструкции.

RUN
subcommand can be used on a docker image to reveal its nature of being a linked list of filesystem layers.

Важное значение имеет количество слоев, используемых в изображении.

  • при отправке или извлечении изображений, поскольку это влияет на количество одновременных загрузок или загрузок.
  • при запуске контейнера, поскольку слои объединяются для создания файловой системы, используемой в контейнере; чем больше слоев задействовано, тем хуже производительность, но на разные серверные части файловой системы это влияет по-разному.

Это имеет несколько последствий для построения изображений. Первый и самый важный совет, который я могу дать:

Совет №1 Убедитесь, что этапы сборки, в которых задействован ваш исходный код, выполняются как можно позже. Докерфайл и не привязаны к предыдущим командам с помощью

RUN
or a
RUN
.

Причина этого в том, что все предыдущие шаги будут кэшированы, и соответствующие слои не нужно будет загружать снова и снова. Это означает более быструю сборку и более быстрые выпуски, а это, вероятно, именно то, что вам нужно. Интересно, что на удивление сложно оптимально использовать кэш докера.

Мой второй совет менее важен, но я считаю его очень полезным с точки зрения обслуживания:

Совет №2 Не пишите сложные команды в Докерфайл а лучше использовать сценарии, которые нужно скопировать и выполнить.

А Докерфайл следование этому совету будет выглядеть так

smallimage     latest        7edeafc01ffe        3 minutes ago    384MB

и так далее. Совет по связыванию нескольких команд с

FROM centos:6

RUN yum -y update  && yum -y install epel-release
has only a limited scope. It is much easier to write with scripts, where you can use functions, etc. to avoid redundancy or for documentation purposes.

Люди, интересующиеся препроцессорами и желающие избежать небольших накладных расходов, вызванных

bigimage     latest        3c5cbfbb4116        2 minutes ago    407MB
steps and are actually generating on-the-fly a Докерфайл где

FROM centos:6

RUN yum -y update 
RUN yum -y install epel-release

последовательности заменяются на

&&

где

gcc --version
is the base64-encoded version of
RUN apt-get install -y gcc\

&& gcc --version\

&& apt-get --purge autoremove -y gcc
.

Мой третий совет предназначен для людей, которые хотят ограничить размер и количество слоев за счет возможной стоимости более длинных сборок.

Совет №3 Используйте

with_c_compiler
-idiom to avoid files present in intermediary layers but not in the resulting filesystem.

Файл, добавленный какой-либо инструкцией докера и удаленный какой-то более поздней инструкцией, отсутствует в результирующей файловой системе, но он дважды упоминается в слоях докера, составляющих создаваемый образ докера. Один раз с именем и полным содержимым на слое в результате инструкции по его добавлению и один раз в виде уведомления об удалении на слое в результате инструкции по его удалению.

Например, предположим, что нам временно нужен компилятор C и некоторый образ, и рассмотрим

with_whatever

(Более реалистичный пример — создание некоторого программного обеспечения с помощью компилятора, а не просто подтверждение его присутствия с помощью

with_c_compiler
flag.)

Фрагмент Dockerfile создает три слоя, первый из которых содержит полный набор gcc, поэтому, даже если он отсутствует в конечной файловой системе, соответствующие данные по-прежнему являются частью образа таким же образом, и их необходимо загружать, выгружать и распаковывать всякий раз, когда окончательное изображение.

# with_c_compiler SIMPLE-COMMAND
#  Execute SIMPLE-COMMAND in a sub-shell with gcc being available.

with_c_compiler()
(

set -e

apt-get install -y gcc

"$@"

trap 'apt-get --purge autoremove -y gcc' EXIT
)

with_c_compiler\

gcc --version
-idiom is a common form in functional programming to isolate resource ownership and resource releasing from the logic using it. It is easy to transpose this idiom to shell-scripting, and we can rephrase the previous commands as the following script, to be used with
COPY & RUN
как в Совет №2.

with

Сложные команды можно превратить в функции, чтобы их можно было передать в

--version
. It is also possible to chain calls of several
# !!! THIS DISPLAYS SOME PROBLEM --- DO NOT USE !!!
RUN apt-get install -y gcc
RUN gcc --version
RUN apt-get --purge autoremove -y gcc
функции, но, возможно, не очень желательны. (Используя более эзотерические особенности оболочки, безусловно, можно сделать
with
accept complex commands, but it is in all aspects preferable to wrap these complex commands into functions.)

Если мы хотим игнорировать совет №2, результирующий фрагмент Dockerfile будет иметь вид

apt_setup.sh

который не так легко читать и поддерживать из-за запутанности. Посмотрите, как вариант сценария оболочки подчеркивает важную часть

while the chained-
RUN base64 --decode … | sh -x
вариант скрывает эту часть посреди шума.

 

Yary79


Рег
25 Oct, 2010

Тем
77

Постов
192

Баллов
587
  • 25, Oct 2024
  • #3

Каждая инструкция, которую вы создаете в своем Dockerfile, приводит к созданию нового слоя изображения. Каждый слой приносит дополнительные данные, которые не всегда являются частью результирующего изображения. Например, если вы добавите файл в один слой, но позже удалите его в другом слое, размер окончательного изображения будет включать размер добавленного файла в форме специального «белого» файла, хотя вы его удалили.

Допустим, у вас есть следующий Dockerfile:

COPY apt_setup.sh /root/
RUN sh -x /root/apt_setup.sh

Размер полученного изображения будет

COPY

Напротив, с «похожим» Dockerfile:

&&

Размер полученного изображения будет

COPY apt_setup.sh /root/
RUN sh -x /root/apt_setup.sh
COPY install_pacakges.sh /root/
RUN sh -x /root/install_packages.sh

Вы получите еще меньший размер, если очистите кеш yum одним оператором RUN.

Итак, вы хотите сохранить баланс между читабельностью/простотой обслуживания и количеством слоев/размером изображения.

 

Doctor_63


Рег
27 Nov, 2019

Тем
78

Постов
208

Баллов
638
  • 25, Oct 2024
  • #4

;
statements represent each one layer. Imagine that one downloads a package, installs it and would like to remove it. If one uses three
&&
утверждений, то размер изображения не будет уменьшаться, поскольку существуют отдельные слои. Если выполнить все команды, используя один
docker inspect
statement the disk image size could be reduced.

 

Yesilcimenahmet


Рег
07 Dec, 2015

Тем
75

Постов
177

Баллов
572
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно