ARG oder ENV, welches in diesem Fall verwenden?

121

Dies könnte vielleicht eine triviale Frage sein, aber das Lesen von Dokumenten für ARG und ENV macht mir die Dinge nicht klar.

Ich baue einen PHP-FPM-Container und möchte die Möglichkeit geben, einige Erweiterungen je nach Benutzeranforderungen zu aktivieren / deaktivieren.

Wäre großartig, wenn dies in der Docker-Datei durch Hinzufügen von Bedingungen und Übergeben von Flags für den Build-Befehl erfolgen könnte, aber AFAIK wird nicht unterstützt.

In meinem Fall und meinem persönlichen Ansatz besteht es darin, beim Starten des Containers ein kleines Skript auszuführen, etwa wie folgt:

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

So sieht mein Dockerfileaus:

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

Hier ist das gesamte Repository, wenn Sie einen tiefen Blick darauf werfen müssen, um zu verstehen, wie ich Dinge mache

Derzeit funktioniert dies, aber ... Wenn ich beispielsweise 20 (eine zufällige Anzahl) Erweiterungen oder eine andere Funktion hinzufügen möchte, die aktiviert oder deaktiviert werden kann, werde ich mit 20 nicht erforderlich ENVenden (da Dockerfile .env nicht unterstützt Dateien) Definition, deren einziger Zweck darin besteht, dieses Flag zu setzen, damit das Skript weiß, was dann zu tun ist ...

  • Ist das der richtige Weg?
  • Soll ich ENVfür diesen Zweck verwenden?

Ich bin offen für Ideen, wenn Sie einen anderen Ansatz haben, um dies zu erreichen, lassen Sie es mich bitte wissen

ReynierPM
quelle
Wenn sich diese Erweiterungen / Funktionen von Build zu Build unterscheiden, sollten Sie ARGsie bei jedem Build mit unterschiedlichen Werten --build-argfestlegen. Sie können weiterhin Standardwerte in der Docker-Datei verwenden. Wenn Sie verwenden ENV, müssten Sie die Docker-Datei selbst für jeden Build bearbeiten, um unterschiedliche Werte festzulegen
AA

Antworten:

214

Aus der Dockerfile-Referenz :

  • Die ARGAnweisung definiert eine Variable, die Benutzer beim Erstellen mit dem Befehl docker build mithilfe des --build-arg <varname>=<value>Flags an den Builder übergeben können .

  • Der ENVBefehl setzt die Umgebungsvariable <key>auf den Wert <value>.
    Die mit festgelegten Umgebungsvariablen ENVbleiben bestehen, wenn ein Container aus dem resultierenden Image ausgeführt wird.

Wenn Sie also eine Anpassung während der Erstellung benötigen , ARGist dies die beste Wahl.
Wenn Sie eine Laufzeitanpassung benötigen (um dasselbe Image mit unterschiedlichen Einstellungen auszuführen), ENVist dies gut geeignet.

Wenn ich 20 (eine zufällige Anzahl) Erweiterungen oder andere Funktionen hinzufügen möchte, die aktiviert oder deaktiviert werden können

Angesichts der Anzahl der beteiligten Kombinationen ENVist es hier am besten, diese Funktionen zur Laufzeit festzulegen.

Sie können jedoch beides kombinieren, indem Sie:

  • Erstellen eines Bildes mit einem bestimmten ARG
  • mit dem ARGalsENV

Das heißt, mit einer Docker-Datei, die Folgendes umfasst:

ARG var
ENV var=${var}

Sie können dann entweder zur Erstellung () ein Image mit einem bestimmten varWert erstellen docker build --build-arg var=xxxoder einen Container mit einem bestimmten Laufzeitwert ( docker run -e var=yyy) ausführen.

VonC
quelle
1
Großartig, aber auf diese ARGkann über das Skript zugegriffen werden, das ich beim Start des Containers ausführe? Wenn das so ist, wie? Könnten Sie Ihre Antwort verbessern, indem Sie ein kleines Beispiel hinzufügen, wie über ein Bash-Skript auf diese zugegriffen werden kann?
ReynierPM
@ReynierPM Sie können, indem Sie in Ihrem Dockerfile (Build - Zeit) erklärt, in Zusatz von ARGein ENV var=${var}: siehe stackoverflow.com/a/33936014/6309 . Verwende beide.
VonC
Wenn ich Ihren Ansatz verwende var, habe ich Recht, egal was ich beim Start mit einer ENV-Variablen auf dem Container erhalte. Sonst folge ich dir überhaupt nicht. Denken Sie daran: Das Skript wird aus einem lokalen Ordner in den Container kopiert und bei der Containerinitialisierung verwendet. Deshalb verwende ich ENV anstelle von ARG, da ich nicht weiß, ob beim Starten des Containers das ARG noch aktiv ist und von innen zugegriffen werden kann ein Bash-Skript.
ReynierPM
Ich habe meine Docker-Datei hinzugefügt, damit Sie sie sich ansehen und wissen können, was ich gerade mache
ReynierPM
1
@ HardeepSingh Beide: ENV ( stackoverflow.com/a/33836848/6309 ) und ARG ( stackoverflow.com/a/41593407/6309 )
VonC
0

Wenn Sie also den Wert einer Umgebungsvariablen für jeden Build auf einen anderen Wert festlegen möchten, können wir diese Werte während der Build-Zeit übergeben und müssen unsere Docker-Datei nicht jedes Mal ändern.

Während ENVeinmal Satz nicht über Kommandozeilenwerte überschrieben werden kann. Wenn unsere Umgebungsvariable unterschiedliche Werte für unterschiedliche Builds haben soll, können wir ARGStandardwerte in unserer Docker-Datei verwenden und festlegen. Und wenn wir diese Werte überschreiben möchten, können wir dies --build-argsbei jedem Build tun , ohne unsere Docker-Datei zu ändern.

Weitere Informationen finden Sie hier .

user2719152
quelle