ARG hay ENV, sử dụng cái nào trong trường hợp này?


122

Đây có thể là một câu hỏi tầm thường nhưng việc đọc tài liệu về ARGENV không giúp tôi hiểu rõ mọi thứ.

Tôi đang xây dựng một vùng chứa PHP-FPM và tôi muốn cung cấp khả năng bật / tắt một số tiện ích mở rộng theo nhu cầu của người dùng.

Sẽ thật tuyệt nếu điều này có thể được thực hiện trong Dockerfile bằng cách thêm các điều kiện và chuyển cờ trên lệnh xây dựng có lẽ nhưng AFAIK không được hỗ trợ.

Trong trường hợp của tôi và cách tiếp cận cá nhân của tôi là chạy một tập lệnh nhỏ khi vùng chứa bắt đầu, giống như sau:

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

Đây là cách tôi Dockerfiletrông như thế này:

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

Đây là toàn bộ kho lưu trữ nếu bạn cần xem xét sâu để hiểu cách tôi đang làm mọi việc

Hiện tại điều này đang hoạt động nhưng ... Nếu tôi muốn thêm, giả sử 20 (một số ngẫu nhiên) tiện ích mở rộng hoặc bất kỳ tính năng nào khác có thể bật | tắt thì tôi sẽ kết thúc bằng 20 không cần thiết ENV(vì Dockerfile không hỗ trợ .env tệp) định nghĩa có mục đích duy nhất sẽ được đặt cờ này để cho tập lệnh biết phải làm gì sau đó ...

  • Đây có phải là cách đúng đắn để làm việc này?
  • Tôi có nên sử dụng ENVcho mục đích này không?

Tôi cởi mở với những ý tưởng nếu bạn có cách tiếp cận khác để đạt được điều này, vui lòng cho tôi biết về nó


Nếu các tiện ích mở rộng / tính năng đó khác nhau giữa các bản dựng này với bản dựng khác, thì bạn nên sử dụng ARGđể đặt chúng với các giá trị khác nhau với mỗi bản dựng đang sử dụng --build-argvà bạn vẫn có thể sử dụng các giá trị mặc định trong Dockerfile. Nếu bạn sử dụng ENV, bạn sẽ cần phải chỉnh sửa Dockerfile cho mỗi bản dựng để đặt các giá trị khác nhau
AA

Câu trả lời:


216

Từ tham chiếu Dockerfile :

  • Các ARGhướng dẫn định nghĩa một biến mà người dùng có thể vượt qua ít build-thời gian để các nhà xây dựng với Docker build lệnh bằng cách sử dụng --build-arg <varname>=<value>lá cờ.

  • Lệnh ENVđặt biến môi trường <key>thành giá trị <value>.
    Các biến môi trường được thiết lập sử dụng ENVsẽ vẫn tồn tại khi một vùng chứa được chạy từ hình ảnh kết quả.

Vì vậy, nếu bạn cần tùy chỉnh thời gian xây dựng , đây ARGlà lựa chọn tốt nhất của bạn.
Nếu bạn cần tùy chỉnh thời gian chạy (để chạy cùng một hình ảnh với các cài đặt khác nhau), ENVrất phù hợp.

Nếu tôi muốn thêm, giả sử 20 (một số ngẫu nhiên) tiện ích mở rộng hoặc bất kỳ tính năng nào khác có thể bật | tắt

Với số lượng kết hợp có liên quan, tốt nhất nên sử dụng ENVđể đặt các tính năng đó trong thời gian chạy.

Nhưng bạn có thể kết hợp cả hai bằng cách:

  • xây dựng một hình ảnh với một ARG
  • sử dụng nó ARGnhư mộtENV

Đó là, với một Dockerfile bao gồm:

ARG var
ENV var=${var}

Sau đó, bạn có thể tạo một hình ảnh với một vargiá trị cụ thể tại build-time ( docker build --build-arg var=xxx) hoặc chạy một vùng chứa với một giá trị thời gian chạy cụ thể ( docker run -e var=yyy)


1
Tuyệt vời nhưng những thứ đó ARGcó thể được truy cập từ tập lệnh tôi đang chạy khi khởi động vùng chứa? Nếu vậy thì làm thế nào? Bạn có thể cải thiện câu trả lời của mình bằng cách thêm một ví dụ nhỏ về cách có thể truy cập chúng từ tập lệnh bash không?
ReynierPM

@ReynierPM bạn có thể, bằng cách tuyên bố trong Dockerfile của bạn (thời gian xây dựng), trong Ngoài ra của ARG, một ENV var=${var}: xem stackoverflow.com/a/33936014/6309 . Sử dụng cả hai.
VonC

Nếu tôi sử dụng cách tiếp cận của bạn thì không có vấn đề gì tôi sẽ kết thúc với một varbiến ENV trên vùng chứa khi nó bắt đầu, tôi đúng? Nếu không, tôi sẽ không theo dõi bạn. Hãy nhớ điều này: tập lệnh được sao chép từ một thư mục cục bộ vào vùng chứa và nó được sử dụng khi khởi tạo vùng chứa, đó là lý do tại sao tôi đang sử dụng ENV thay vì ARG vì tôi không biết liệu khi khởi động vùng chứa thì ARG vẫn còn sống và có thể được truy cập từ bên trong một tập lệnh bash.
ReynierPM

Tôi đã thêm Dockerfile của tôi vì vậy bạn có thể có một cái nhìn vào nó và biết những gì tôi đang làm hiện nay
ReynierPM

1
@HardeepSingh Cả hai: ENV ( stackoverflow.com/a/33836848/6309 ) và ARG ( stackoverflow.com/a/41593407/6309 )
VonC

0

Vì vậy, nếu muốn đặt giá trị của một biến môi trường thành một cái gì đó khác cho mọi bản dựng thì chúng ta có thể chuyển các giá trị này trong thời gian xây dựng và chúng ta không cần phải thay đổi tệp docker của mình mỗi lần.

Trong khi ENV, một khi thiết lập không thể được ghi đè thông qua các giá trị dòng lệnh. Vì vậy, nếu chúng ta muốn biến môi trường của mình có các giá trị khác nhau cho các bản dựng khác nhau thì chúng ta có thể sử dụng ARGvà đặt các giá trị mặc định trong tệp docker của mình. Và khi chúng ta muốn ghi đè các giá trị này thì chúng ta có thể làm như vậy bằng cách sử dụng --build-argsở mọi bản dựng mà không cần thay đổi tệp docker của mình.

Để biết thêm chi tiết, bạn có thể tham khảo này .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.