ARG czy ENV, którego użyć w tym przypadku?

122

To może być trywialne pytanie, ale czytanie dokumentacji dla ARG i ENV nie wyjaśnia mi sprawy.

Buduję kontener PHP-FPM i chcę dać możliwość włączania / wyłączania niektórych rozszerzeń na potrzeby użytkownika.

Byłoby wspaniale, gdyby można to zrobić w pliku Dockerfile, dodając warunki warunkowe i przekazując flagi w poleceniu kompilacji, być może, ale AFAIK nie jest obsługiwany.

W moim przypadku i moim osobistym podejściem jest uruchomienie małego skryptu podczas uruchamiania kontenera, coś takiego:

#!/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 "$@"

Tak Dockerfilewygląda mój wygląd:

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

Oto całe repozytorium, jeśli potrzebujesz dokładniejszego przyjrzenia się, aby zrozumieć, jak robię rzeczy

Obecnie to działa, ale ... Jeśli chcę dodać, powiedzmy, 20 (losową liczbę) rozszerzeń lub jakąkolwiek inną funkcję, którą można włączyć | wyłączyć, skończę z 20 niepotrzebnymi ENV(ponieważ Dockerfile nie obsługuje .env files), której jedynym celem byłoby ustawienie tej flagi, aby skrypt wiedział, co wtedy zrobić ...

  • Czy to jest właściwy sposób?
  • Powinienem używać ENVdo tego celu?

Jestem otwarty na pomysły, jeśli masz inne podejście do osiągnięcia tego celu, daj mi o tym znać

ReynierPM
źródło
Jeśli te rozszerzenia / funkcje będą się różnić w zależności od kompilacji, należy użyć, ARGaby ustawić dla nich różne wartości przy każdej kompilacji --build-arg, i nadal można używać wartości domyślnych w pliku Dockerfile. Jeśli używasz ENV, musisz edytować sam plik Dockerfile dla każdej kompilacji, aby ustawić inne wartości
AA

Odpowiedzi:

217

Z odwołania do Dockerfile :

  • ARGInstrukcja definiuje zmienną, że użytkownicy mogą przechodzić w czasie kompilacji do konstruktora z poleceniem doker kompilacji przy użyciu --build-arg <varname>=<value>flagi.

  • ENVInstrukcja ustawia zmienną środowiskową <key>do wartości <value>.
    Zmienne środowiskowe ustawione przy użyciu ENVzostaną zachowane, gdy kontener zostanie uruchomiony z obrazu wynikowego.

Więc jeśli potrzebujesz dostosowania czasu budowy , ARGjest to najlepszy wybór.
Jeśli potrzebujesz dostosowania w czasie wykonywania (aby uruchomić ten sam obraz z różnymi ustawieniami), ENVjest dobrze dopasowany.

Jeśli chcę dodać, powiedzmy, 20 (losową liczbę) rozszerzeń lub jakąkolwiek inną funkcję, którą można włączyć | wyłączyć

Biorąc pod uwagę liczbę kombinacji, ENVw tym przypadku najlepiej jest użyć do ustawienia tych funkcji w czasie wykonywania.

Ale możesz połączyć oba przez:

  • budowanie wizerunku z konkretnym ARG
  • używając tego ARGjako plikuENV

Oznacza to, że z plikiem Dockerfile zawierającym:

ARG var
ENV var=${var}

Następnie możesz zbudować obraz z określoną varwartością w czasie kompilacji ( docker build --build-arg var=xxx) lub uruchomić kontener z określoną wartością w czasie wykonywania ( docker run -e var=yyy)

VonC
źródło
1
Świetnie, ale ARGmożna uzyskać do nich dostęp ze skryptu, który uruchamiam podczas uruchamiania kontenera? Jeśli tak to jak? Czy mógłbyś poprawić swoją odpowiedź, dodając mały przykład o tym, jak można uzyskać do nich dostęp ze skryptu bash?
ReynierPM
@ReynierPM można, deklarując w Dockerfile (czas budowy), w dodatku z ARGAn ENV var=${var}: patrz stackoverflow.com/a/33936014/6309 . Użyj obu.
VonC,
Jeśli zastosuję twoje podejście, to bez względu na to, co skończę ze varzmienną ENV na kontenerze, gdy zacznie, mam rację? W przeciwnym razie w ogóle cię nie śledzę. Pamiętaj: skrypt jest kopiowany z folderu lokalnego do kontenera i jest używany podczas inicjalizacji kontenera, dlatego używam ENV zamiast ARG, ponieważ nie wiem, czy po uruchomieniu kontenera ARG wciąż żyje i można uzyskać do niego dostęp od wewnątrz skrypt bash.
ReynierPM
Dodałem mój plik Dockerfile, abyś mógł go zobaczyć i wiedzieć, co obecnie robię
ReynierPM
1
@HardeepSingh Oba: ENV ( stackoverflow.com/a/33836848/6309 ) i ARG ( stackoverflow.com/a/41593407/6309 )
VonC
0

Więc jeśli chcesz ustawić wartość zmiennej środowiskowej na coś innego dla każdej kompilacji, możemy przekazać te wartości w czasie kompilacji i nie musimy za każdym razem zmieniać naszego pliku docker.

Podczas gdy ENVraz ustawione nie można nadpisać wartościami wiersza poleceń. Tak więc, jeśli chcemy, aby nasza zmienna środowiskowa miała różne wartości dla różnych kompilacji, możemy użyć ARGi ustawić wartości domyślne w naszym pliku docker. A kiedy chcemy nadpisać te wartości, możemy to zrobić za pomocą--build-args każdej kompilacji bez zmiany naszego pliku docker.

Aby uzyskać więcej informacji, można odwołać się w tym .

user2719152
źródło