В моем файле докера действительно имеет значение, помещаю ли я RUN
команды в одну строку или нет? Сокращает ли их размещение в одну строку время сборки?
RUN apt-get update
RUN apt-get -y install --no-install-recommends python3
RUN apt-get -y install --no-install-recommends open-vm-tools
против.
RUN apt-get update && apt-get -y install --no-install-recommends python3
RUN apt-get -y install --no-install-recommends open-vm-tools
Минимизируя количество слоев, вы уменьшаете размер изображения и, конечно же, время сборки. Это также рекомендуется в раздел лучших практик «Минимизировать количество слоев».
In older versions of Docker, it was important that you minimized the number of layers in your images to ensure they were performant. The following features were added to reduce this limitation.
- Only the instructions RUN, COPY, ADD create layers. Other instructions create temporary intermediate images, and do not increase the size of the build.
...
С практической точки зрения, затраты времени на сборку и выполнение одной команды RUN по сравнению с несколькими будут незаметны, и я бы не стал пытаться оптимизировать здесь исключительно ради производительности.
В конкретном примере, который вы показываете, верно несколько вещей:
Инструмент Debian APT сам по себе имеет нетривиальное время запуска; и отдельно от одной команды RUN против нескольких, одна apt-get install
против двух будет быстрее.
RUN apt-get install -y --no-install-recommends python3 open-vm-tools
Debian и Ubuntu довольно часто обновляют свои репозитории, и когда они это делают, ссылки на пакеты, которые были в apt-get update
на прошлой неделе, перестают работать. Между тем, кэширование слоя Docker попытается избежать повторного запуска уже выполненного шага. Если вы собрали свой образ неделю назад, Docker скажет: «Я уже сделал это RUN apt-get update
, поэтому мне не нужно запускать его снова»; но это означает, что он кэширует устаревший индекс пакета. Важно запускать apt-get update
и apt-get install
на одном шаге RUN.
RUN apt-get update \
&& apt-get install -y --no-install-recommends python3 open-vm-tools
И вообще:
Если у вас есть какие-то шаги очистки, которые вы хотите запустить, важно запустить их на одном шаге RUN. Эта последовательность создает слой после этапа сборки, поэтому шаг RUN rm
на самом деле не уменьшает окончательный слой.
# All of this example should be combined into a single RUN step
RUN tar xzf package-1.2.3.tar.gz
RUN cd package-1.2.3 && ./configure && make && make install
# There is a layer here including the build tree
RUN rm -rf package-1.2.3
Если вы работаете с Dockerfile, может быть проще разделить его на множество небольших команд RUN во время отладки, а затем объединить их. Это прекрасно, и вы должны получить идентичное дерево в конце.
# I'm trying to figure out the configure options so I might
RUN tar xzf package-1.2.3.tar.gz
RUN cd package-1.2.3 && ./configure --some-option
RUN cd package-1.2.3 && make
Если вы не очистите кеш apt в конце вашего «одного лайнера», вы на самом деле не достигнете многого. К вашему изображению по-прежнему добавляется большой слой.
Основная идея состоит в том, чтобы поместить все установки в одну строку и закончить эту строку очисткой, чтобы, когда докер сохранял этот слой (перед переходом к следующей команде), он сохранял только вновь установленное программное обеспечение без всех загрузок и кеша, которые все равно больше не используются.
Что касается скорости, возможно, вы немного выиграете, написав больше на 1 строку, но я не думаю, что это так уж много. Конечно, если у вас их сотни, вы увидите разницу.