Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як працюють heredoc-и в Dockerfile і чим вони кращі за ланцюжки команд через &&?

Класичний спосіб виконати кілька команд в одному шарі - довгий ланцюжок через && і \:

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.

Докладніше в документації: Dockerfile: here-documents

Схожі питання