ARG o ENV, quale usare in questo caso?


122

Questa potrebbe essere una domanda banale, ma leggere documenti per ARG ed ENV non mi rende le cose chiare.

Sto costruendo un contenitore PHP-FPM e voglio dare la possibilità di abilitare / disabilitare alcune estensioni sulle esigenze dell'utente.

Sarebbe bello se questo potesse essere fatto nel Dockerfile aggiungendo condizionali e passando flag sul comando di compilazione, forse, ma AFAIK non è supportato.

Nel mio caso e il mio approccio personale è quello di eseguire un piccolo script all'avvio del contenitore, qualcosa di simile al seguente:

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

Ecco come Dockerfileappare il mio :

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

Ecco l'intero repository se hai bisogno di dare uno sguardo approfondito per capire come sto facendo le cose

Attualmente funziona ma ... Se voglio aggiungere diciamo 20 (un numero casuale) di estensioni o qualsiasi altra funzionalità che può essere abilitata | disabilitata, ENVfinirò con 20 non necessarie (perché Dockerfile non supporta .env file) definizione il cui unico scopo sarebbe impostare questo flag per far sapere allo script cosa fare allora ...

  • È questo il modo giusto per farlo?
  • Dovrei usare ENVper questo scopo?

Sono aperto alle idee, se hai un approccio diverso per raggiungere questo obiettivo, fammelo sapere


Se tali estensioni / funzionalità sarebbero diverse da una build all'altra, dovresti usarle ARGper impostarle con valori diversi con ciascuna build che usa --build-arge puoi ancora usare i valori predefiniti nel Dockerfile. Se lo usi ENV, dovresti modificare il Dockerfile stesso per ogni build per impostare valori diversi
AA

Risposte:


216

Dal riferimento Dockerfile :

  • L' ARGistruzione definisce una variabile che gli utenti possono passare in fase di compilazione al builder con il comando docker build utilizzando il --build-arg <varname>=<value>flag.

  • L' ENVistruzione imposta la variabile d'ambiente <key>sul valore <value>.
    Le variabili di ambiente impostate utilizzando ENVpersisteranno quando un contenitore viene eseguito dall'immagine risultante.

Quindi, se hai bisogno di personalizzazione del tempo di costruzione , ARGè la scelta migliore.
Se è necessaria la personalizzazione in fase di esecuzione (per eseguire la stessa immagine con impostazioni diverse), ENVè adatto.

Se voglio aggiungere diciamo 20 (un numero casuale) di interni o qualsiasi altra funzione che può essere abilitata | disabilitata

Dato il numero di combinazioni coinvolte, ENVqui è meglio usare per impostare quelle funzionalità in fase di esecuzione.

Ma puoi combinare entrambi :

  • costruire un'immagine con uno specifico ARG
  • usandolo ARGcome fileENV

Cioè, con un Dockerfile che include:

ARG var
ENV var=${var}

È quindi possibile creare un'immagine con un varvalore specifico in fase di compilazione ( docker build --build-arg var=xxx) o eseguire un contenitore con un valore di runtime specifico ( docker run -e var=yyy)


1
Ottimo ma è ARGpossibile accedervi dallo script che sto eseguendo all'avvio del contenitore? Se é cosi, come? Potresti migliorare la tua risposta aggiungendo un piccolo esempio su come è possibile accedervi da uno script bash?
ReynierPM

@ReynierPM si può, dichiarando nel Dockerfile (tempo di costruzione), in aggiunta di ARGun ENV var=${var}: vedi stackoverflow.com/a/33936014/6309 . Usali entrambi.
VonC

Se uso il tuo approccio, non importa cosa varfinirò con una variabile ENV sul contenitore quando inizierà, ho ragione? Altrimenti non ti sto seguendo affatto. Ricorda questo: lo script viene copiato da una cartella locale al contenitore e viene utilizzato durante l'inizializzazione del contenitore, ecco perché sto usando ENV invece di ARG perché non so se quando il contenitore si avvia l'ARG è ancora attivo ed è possibile accedervi dall'interno uno script bash.
ReynierPM

Ho aggiunto il mio Dockerfile in modo che tu possa esaminarlo e sapere cosa sto facendo attualmente
ReynierPM

1
@HardeepSingh Entrambi: ENV ( stackoverflow.com/a/33836848/6309 ) e ARG ( stackoverflow.com/a/41593407/6309 )
VonC

0

Quindi, se si desidera impostare il valore di una variabile di ambiente su qualcosa di diverso per ogni build, allora possiamo passare questi valori durante il tempo di compilazione e non abbiamo bisogno di cambiare il nostro file docker ogni volta.

Mentre ENV, una volta impostato non può essere sovrascritto tramite i valori della riga di comando. Quindi, se vogliamo che la nostra variabile d'ambiente abbia valori diversi per build differenti, allora potremmo usare ARGe impostare valori predefiniti nel nostro file docker. E quando vogliamo sovrascrivere questi valori, possiamo farlo usando --build-argsad ogni build senza cambiare il nostro file docker.

Per maggiori dettagli, puoi fare riferimento a questo .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.