Класичний спосіб виконати кілька команд в одному шарі - довгий ланцюжок через && і \:
RUN apk add --no-cache --virtual .build-deps $PHPIZE_DEPS icu-dev libzip-dev \
&& docker-php-ext-install intl zip pdo_pgsql \
&& pecl install redis \
&& docker-php-ext-enable redis \
&& apk del .build-deps
Важко читати, легко забути \ чи &&, неможливо коментувати окремі рядки.
Heredoc у RUN (сучасний синтаксис Dockerfile, працює з BuildKit):
# syntax=docker/dockerfile:1
RUN <<EOF
set -eux
apk add --no-cache --virtual .build-deps $PHPIZE_DEPS icu-dev libzip-dev
docker-php-ext-install intl zip pdo_pgsql
# Redis з PECL
pecl install redis
docker-php-ext-enable redis
apk del .build-deps
EOF
Увесь блок виконується одним RUN - тобто одним шаром, як і ланцюжок з &&.
Важливо: set -e. У ланцюжку && помилка будь-якої команди зупиняє виконання. У heredoc команди виконуються як скрипт - без set -e збирання продовжиться після помилки, і проблему помітять лише в образі. set -eux - зупинитися на помилці (e), на невизначених змінних (u) і показувати команди у виводі (x).
Інший інтерпретатор:
RUN <<EOF python3
print("Генерація конфігурації")
EOF
Heredoc у COPY - створити файл прямо в Dockerfile без окремого файлу в репозиторії:
COPY <<EOF /usr/local/etc/php/conf.d/opcache.ini
opcache.enable=1
opcache.validate_timestamps=0
opcache.memory_consumption=256
EOF
Зручно для невеликих конфігураційних файлів, що стосуються лише образу.
Підстановка змінних: у <<EOF змінні збирання (ARG) підставляються; щоб передати текст буквально (зокрема $ для оболонки всередині), - лапки навколо маркера: <<'EOF'.
Коли heredoc не потрібен: одна-дві короткі команди читаються і в звичайному RUN. Для довгих скриптів (понад десяток рядків) краще окремий файл-скрипт у репозиторії, який можна перевірити ShellCheck і викликати з RUN.