ARG або ENV, який використовувати в цьому випадку?


122

Це може бути тривіальним питанням, але читання документів для 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 файли) визначення, єдиною метою якого було б встановити цей прапор, нехай сценарій знає, що робити тоді ...

  • Це правильний спосіб зробити це?
  • Чи варто використовувати ENVдля цієї мети?

Я відкритий до ідей, якщо у вас інший підхід для цього, будь ласка, дайте мені знати про це


Якщо ці розширення / функції відрізнятимуться від однієї збірки до іншої, то слід використовувати їх ARGдля встановлення різних значень для кожної збірки за допомогою --build-arg, і ви все одно можете використовувати значення за замовчуванням у Dockerfile. Якщо ви використовуєте ENV, вам потрібно буде відредагувати сам Dockerfile для кожної збірки, щоб встановити різні значення
AA

Відповіді:


216

З посилання на Dockerfile :

  • ARGІнструкція визначає змінну , що користувачі можуть проходити при побудові часу будівельника з командою докер збірки , використовуючи --build-arg <varname>=<value>прапор.

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

Тож якщо вам потрібна налаштування часу побудови , ARGце ваш найкращий вибір.
Якщо вам потрібна налаштування часу виконання (для запуску одного і того ж зображення з різними налаштуваннями), ENVдобре підійде.

Якщо я хочу додати, скажімо, 20 (випадкове число) розширень або будь-яку іншу функцію, яку можна включити | відключити

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

Але ви можете комбінувати обидва :

  • побудова образу із конкретним ARG
  • використовуючи це ARGяк anENV

Тобто, з Dockerfile, що включає:

ARG var
ENV var=${var}

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


1
Чудово, але до них ARGможна дійти зі скрипту, який я запускаю при запуску контейнера? Якщо так, як? Не могли б ви покращити свою відповідь, додавши невеликий приклад про те, як можна отримати доступ до скрипту bash?
ReynierPM

@ReynierPM ви можете, оголосивши в своєму Dockerfile (час збирання), в доповнення з ARG, ENV var=${var}: см stackoverflow.com/a/33936014/6309 . Використовуйте обидва.
VonC

Якщо я використовую ваш підхід, то незалежно від того, що я закінчую varENV-змінною на контейнері, коли він запускається, я маю рацію? Інакше я зовсім не слідкую за тобою. Пам'ятайте це: сценарій копіюється з локальної папки в контейнер і використовується при ініціалізації контейнера, тому я використовую ENV замість ARG, тому що я не знаю, коли контейнер запустить ARG ще живий і до нього можна отримати доступ зсередини баш сценарій.
ReynierPM

Я додав свій Dockerfile, щоб ви могли подивитися на нього і знати, що я зараз роблю
ReynierPM

1
@HardeepSingh Обидва: ENV ( stackoverflow.com/a/33836848/6309 ) і ARG ( stackoverflow.com/a/41593407/6309 )
VonC

0

Отже, якщо ви хочете встановити значення змінної середовища на щось інше для кожної збірки, то ми можемо передавати ці значення протягом часу збирання, і нам не потрібно міняти наш файл докера кожен раз.

У той час як ENVодин раз встановлений не може бути перезаписаний через значення командного рядка. Отже, якщо ми хочемо, щоб наша змінна середовище мала різні значення для різних збірок, тоді ми могли б використовувати ARGта встановлювати значення за замовчуванням у нашому файлі докера. І коли ми хочемо перезаписати ці значення, ми можемо це зробити, використовуючи --build-argsкожну збірку, не змінюючи наш файл докера.

Для більш детальної інформації ви можете посилатися на це .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.