ARG atau ENV, mana yang akan digunakan dalam kasus ini?

122

Ini mungkin pertanyaan yang sepele tetapi membaca dokumen untuk ARG dan ENV tidak menjelaskan semuanya kepada saya.

Saya membangun wadah PHP-FPM dan saya ingin memberikan kemampuan untuk mengaktifkan / menonaktifkan beberapa ekstensi sesuai kebutuhan pengguna.

Akan lebih bagus jika ini bisa dilakukan di Dockerfile dengan menambahkan kondisional dan meneruskan flag pada perintah build mungkin tetapi AFAIK tidak didukung.

Dalam kasus saya dan pendekatan pribadi saya adalah menjalankan skrip kecil saat penampung dimulai, seperti berikut ini:

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

Seperti inilah Dockerfilepenampilanku:

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

Berikut adalah keseluruhan repositori jika Anda perlu melihat lebih dalam untuk memahami bagaimana saya melakukan sesuatu

Saat ini ini berfungsi tetapi ... Jika saya ingin menambahkan katakanlah 20 (nomor acak) ekstensi atau fitur lain yang dapat diaktifkan | nonaktifkan maka saya akan mengakhiri dengan 20 tidak diperlukan ENV(karena Dockerfile tidak mendukung .env files) definisi yang satu-satunya tujuan akan ditetapkan bendera ini untuk membiarkan skrip tahu apa yang harus dilakukan kemudian ...

  • Apakah ini cara yang benar untuk melakukannya?
  • Haruskah saya gunakan ENVuntuk tujuan ini?

Saya terbuka untuk ide jika Anda memiliki pendekatan berbeda untuk mencapai ini, beri tahu saya tentang hal itu

ReynierPM
sumber
Jika ekstensi / fitur tersebut akan berbeda dari satu build ke build lainnya, maka Anda harus menggunakan ARGuntuk mengaturnya dengan nilai yang berbeda dengan setiap build yang digunakan --build-arg, dan Anda masih dapat menggunakan nilai default di Dockerfile. Jika Anda menggunakan ENV, Anda perlu mengedit Dockerfile itu sendiri untuk setiap build guna menetapkan nilai yang berbeda
AA

Jawaban:

216

Dari referensi Dockerfile :

  • The ARGinstruksi mendefinisikan variabel yang pengguna dapat lulus pada build-waktu untuk pembangun dengan perintah buruh pelabuhan membangun menggunakan --build-arg <varname>=<value>bendera.

  • The ENVinstruksi set variabel lingkungan <key>untuk nilai <value>.
    Variabel lingkungan yang disetel menggunakan ENVakan tetap ada saat penampung dijalankan dari gambar yang dihasilkan.

Jadi, jika Anda membutuhkan kustomisasi waktu pembuatan , itu ARGadalah pilihan terbaik Anda.
Jika Anda membutuhkan kustomisasi run-time (untuk menjalankan gambar yang sama dengan pengaturan yang berbeda), ENVsangat cocok.

Jika saya ingin menambahkan katakanlah 20 (nomor acak) ekstensi atau fitur lain yang dapat mengaktifkan | nonaktifkan

Mengingat jumlah kombinasi yang terlibat, penggunaan ENVuntuk menyetel fitur tersebut pada waktu proses adalah yang terbaik di sini.

Tapi Anda bisa menggabungkan keduanya dengan:

  • membangun citra dengan spesifik ARG
  • menggunakan itu ARGsebagai fileENV

Artinya, dengan Dockerfile termasuk:

ARG var
ENV var=${var}

Anda kemudian dapat membuat gambar dengan varnilai tertentu pada waktu build ( docker build --build-arg var=xxx), atau menjalankan penampung dengan nilai waktu proses tertentu ( docker run -e var=yyy)

VonC
sumber
1
Hebat tapi itu ARGbisa diakses dari skrip yang saya jalankan saat startup kontainer? Jika ya, bagaimana caranya? Bisakah Anda meningkatkan jawaban Anda dengan menambahkan sedikit contoh tentang bagaimana itu dapat diakses dari skrip bash?
ReynierPM
@ReynierPM Anda dapat, dengan menyatakan dalam Dockerfile (build waktu) Anda, di samping dari ARG, sebuah ENV var=${var}: lihat stackoverflow.com/a/33936014/6309 . Gunakan keduanya.
VonC
Jika saya menggunakan pendekatan Anda maka tidak peduli apa yang saya akan berakhir dengan varvariabel ENV pada wadah ketika itu dimulai, saya benar? Jika tidak, saya tidak akan mengikuti Anda sama sekali. Ingat ini: skrip disalin dari folder lokal ke container dan digunakan saat inisialisasi container, itulah mengapa saya menggunakan ENV daripada ARG karena saya tidak tahu apakah kapan container memulai ARG masih hidup dan dapat diakses dari dalam skrip pesta.
ReynierPM
Saya telah menambahkan Dockerfile saya sehingga Anda dapat melihatnya dan mengetahui apa yang saya lakukan saat ini
ReynierPM
1
@HardeepSingh Keduanya: ENV ( stackoverflow.com/a/33836848/6309 ) dan ARG ( stackoverflow.com/a/41593407/6309 )
VonC
0

Jadi, jika ingin menyetel nilai variabel lingkungan ke sesuatu yang berbeda untuk setiap build, kita dapat meneruskan nilai ini selama waktu build dan kita tidak perlu mengubah file buruh pelabuhan setiap saat.

Sementara ENV, setelah disetel tidak dapat ditimpa melalui nilai baris perintah. Jadi, jika kita ingin variabel lingkungan kita memiliki nilai yang berbeda untuk build yang berbeda maka kita bisa menggunakanARG dan mengatur nilai default di file buruh pelabuhan kita. Dan ketika kami ingin menimpa nilai-nilai ini maka kami dapat melakukannya menggunakan --build-argsdi setiap build tanpa mengubah file buruh pelabuhan kami.

Untuk lebih jelasnya, Anda bisa merujuk ini .

pengguna2719152
sumber