ARG или ENV, что использовать в этом случае?

123

Это может быть тривиальный вопрос, но чтение документации по ARG и ENV не проясняет мне ситуацию.

Я создаю контейнер PHP-FPM и хочу дать возможность включать / отключать некоторые расширения по потребностям пользователя.

Было бы здорово, если бы это можно было сделать в Dockerfile, добавив условные обозначения и передав флаги в команду сборки, но AFAIK не поддерживается.

В моем случае и мой личный подход - запускать небольшой скрипт при запуске контейнера, примерно так:

#!/bin/sh   
set -e

RESTART="false"

# This script will be placed in /config/init/ and run when container starts.
if  [ "$INSTALL_XDEBUG" == "true" ]; then
    printf "\nInstalling Xdebug ...\n"
    yum install -y  php71-php-pecl-xdebug
    RESTART="true"
fi
...   
if  [ "$RESTART" == "true" ]; then
    printf "\nRestarting php-fpm ...\n"
    supervisorctl restart php-fpm
fi

exec "$@"

Вот как Dockerfileвыглядит мой :

FROM reynierpm/centos7-supervisor
ENV TERM=xterm \
    PATH="/root/.composer/vendor/bin:${PATH}" \
    INSTALL_COMPOSER="false" \
    COMPOSER_ALLOW_SUPERUSER=1 \
    COMPOSER_ALLOW_XDEBUG=1 \
    COMPOSER_DISABLE_XDEBUG_WARN=1 \
    COMPOSER_HOME="/root/.composer" \
    COMPOSER_CACHE_DIR="/root/.composer/cache" \
    SYMFONY_INSTALLER="false" \
    SYMFONY_PROJECT="false" \
    INSTALL_XDEBUG="false" \
    INSTALL_MONGO="false" \
    INSTALL_REDIS="false" \
    INSTALL_HTTP_REQUEST="false" \
    INSTALL_UPLOAD_PROGRESS="false" \
    INSTALL_XATTR="false"

RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \
                   https://rpms.remirepo.net/enterprise/remi-release-7.rpm
RUN yum install -y  \
        yum-utils \
        git \
        zip \
        unzip \
        nano \
        wget \
        php71-php-fpm \
        php71-php-cli \
        php71-php-common \
        php71-php-gd \
        php71-php-intl \
        php71-php-json \
        php71-php-mbstring \
        php71-php-mcrypt \
        php71-php-mysqlnd \
        php71-php-pdo \
        php71-php-pear \
        php71-php-xml \
        php71-pecl-apcu \
        php71-php-pecl-apfd \
        php71-php-pecl-memcache \
        php71-php-pecl-memcached \
        php71-php-pecl-zip && \
        yum clean all && rm -rf /tmp/yum*

RUN ln -sfF /opt/remi/php71/enable /etc/profile.d/php71-paths.sh && \
    ln -sfF /opt/remi/php71/root/usr/bin/{pear,pecl,phar,php,php-cgi,phpize} /usr/local/bin/. && \
    mv -f /etc/opt/remi/php71/php.ini /etc/php.ini && \
    ln -s /etc/php.ini /etc/opt/remi/php71/php.ini && \
    rm -rf /etc/php.d && \
    mv /etc/opt/remi/php71/php.d /etc/. && \
    ln -s /etc/php.d /etc/opt/remi/php71/php.d

COPY container-files /
RUN chmod +x /config/bootstrap.sh
WORKDIR /data/www
EXPOSE 9001

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

В настоящее время это работает, но ... Если я хочу добавить, скажем, 20 (случайное число) расширений или любую другую функцию, которую можно включить | отключить, тогда я ENVзакончу с 20 ненужными (потому что Dockerfile не поддерживает .env files), единственной целью которого будет установка этого флага, чтобы сценарий знал, что делать дальше ...

  • Это правильный способ сделать это?
  • Стоит ли использовать ENVдля этой цели?

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

ReynierPM
источник
Если эти расширения / функции будут отличаться от одной сборки к другой, то вы должны использовать, ARGчтобы установить для них разные значения с каждой используемой сборкой --build-arg, и вы все равно можете использовать значения по умолчанию в Dockerfile. Если вы используете ENV, вам нужно будет отредактировать сам Dockerfile для каждой сборки, чтобы установить разные значения
AA

Ответы:

218

Из ссылки Dockerfile :

  • ARGИнструкция определяет переменную , что пользователи могут проходить при построении времени строителя с командой докер сборки , используя --build-arg <varname>=<value>флаг.

  • ENVИнструкция устанавливает переменную окружения <key>к значению <value>.
    Переменные среды, заданные с помощью, ENVбудут сохраняться при запуске контейнера из полученного изображения.

Так что, если вам нужна настройка во время сборки , ARGэто ваш лучший выбор.
Если вам нужна настройка во время выполнения (для запуска одного и того же образа с разными настройками), ENVэто хорошо подходит.

Если я хочу добавить, скажем, 20 (случайное число) расширений или любую другую функцию, которую можно включить | отключить

Учитывая количество задействованных комбинаций, используя ENV лучше всего для установки этих функций во время выполнения.

Но вы можете комбинировать и то, и другое :

  • создание образа с конкретным ARG
  • используя это ARGкакENV

То есть с Dockerfile, включающим:

ARG var
ENV var=${var}

Затем вы можете либо создать образ с определенным varзначением в build-time ( docker build --build-arg var=xxx), либо запустить контейнер с определенным значением времени выполнения ( docker run -e var=yyy)

VonC
источник
1
Отлично, но к ним ARGможно получить доступ из сценария, который я запускаю при запуске контейнера? Если да, то как? Не могли бы вы улучшить свой ответ, добавив небольшой пример того, как к ним можно получить доступ из сценария bash?
ReynierPM
@ReynierPM вы можете, объявив в своем Dockerfile (время сборки), в дополнение из ARG, ENV var=${var}: см stackoverflow.com/a/33936014/6309 . Используйте оба.
VonC
Если я использую ваш подход, то независимо от того, что я varполучу с переменной ENV в контейнере при его запуске, я прав? Иначе я вообще не слежу за тобой. Помните: сценарий копируется из локальной папки в контейнер и используется при инициализации контейнера, поэтому я использую ENV вместо ARG, потому что я не знаю, работает ли ARG при запуске контейнера и может быть доступен изнутри. сценарий bash.
ReynierPM
Я добавил свой Dockerfile, чтобы вы могли взглянуть на него и знать, чем я сейчас занимаюсь
ReynierPM
1
@HardeepSingh Оба: ENV ( stackoverflow.com/a/33836848/6309 ) и ARG ( stackoverflow.com/a/41593407/6309 )
VonC
0

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

В ENVто время как однажды установленный не может быть перезаписан через значения командной строки. Итак, если мы хотим, чтобы наша переменная среды имела разные значения для разных сборок, мы могли бы использовать ARGи устанавливать значения по умолчанию в нашем файле докеров. И когда мы хотим перезаписать эти значения, мы можем сделать это, используя--build-args при каждой сборке, не изменяя наш файл докеров.

Для получения дополнительной информации вы можете обратиться к этому .

user2719152
источник