ARG或ENV,在这种情况下使用哪个?


121

这可能是一个琐碎的问题,但阅读ARGENV的文档对我而言并不清楚。

我正在构建一个PHP-FPM容器,我想提供启用/禁用某些用户需求扩展的功能。

如果可以在Dockerfile中通过添加条件并在build命令上传递标志来做到这一点,那就太好了,但不支持AFAIK。

就我而言,我的个人方法是在容器启动时运行一个小的脚本,如下所示:

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

这是我的Dockerfile样子:

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

如果您需要深入了解我的工作方式,则这里是整个存储库

目前这是可行的,但是...如果我想添加20(随机数)个扩展名或可以启用的任何其他功能,那么我将以20个不必要的结尾ENV(因为Dockerfile不支持.env文件)定义,其唯一目的将是设置此标志,以使脚本知道该怎么办...

  • 这是正确的方法吗?
  • 我应该ENV为此目的使用吗?

如果您有其他方法可以实现此目标,我欢迎您提出意见,请让我知道


如果这些扩展名/功能因一个版本而异,那么您应该使用ARG来为每个版本设置不同的扩展名--build-arg,并且仍然可以在Dockerfile中使用默认值。如果使用ENV,则需要为每个构建都编辑Dockerfile本身以设置不同的值
AA

Answers:


216

Dockerfile参考

  • ARG指令定义了一个变量,用户可以在构建时使用docker build命令使用该变量将--build-arg <varname>=<value>标志传递给构建器。

  • ENV指令将环境变量<key>设置为value <value>。从结果映像运行容器时,
    使用设置的环境变量ENV将保留。

因此,如果您需要构建时自定义,ARG则是最佳选择。
如果您需要运行时自定义(以不同的设置运行同一图像),ENV则非常适合。

如果我想添加扩展名或20个(随机数)或可以启用或禁用的任何其他功能

给定涉及的组合数量,ENV最好在运行时设置这些功能。

但是您可以通过以下两种方式将两者结合

  • 用特定的图像 ARG
  • 用它ARG作为一个ENV

也就是说,使用包含以下内容的Dockerfile:

ARG var
ENV var=${var}

然后,您可以var在构建时(docker build --build-arg var=xxx)构建具有特定值的映像,或运行具有特定运行时值(docker run -e var=yyy)的容器


1
太好了,但是ARG可以从我在容器启动时运行的脚本中进行访问吗?如果可以,怎么办?您能否通过添加一个有关如何从bash脚本访问它们的小例子来改善答案?
ReynierPM

@ReynierPM你可以通过在你的Dockerfile(编译时间)宣布,在另外ARG,一ENV var=${var}:看stackoverflow.com/a/33936014/6309。同时使用。
VonC

如果我使用您的方法,那么无论var在容器启动时最终在容器上添加一个ENV变量,对吗?否则,我根本不会关注您。记住这一点:脚本从本地文件夹复制到容器中,并在容器初始化时使用,这就是为什么我使用ENV而不是ARG的原因,因为我不知道容器启动时ARG是否仍然有效并且可以从内部访问bash脚本。
ReynierPM

我添加了我的Dockerfile,以便您可以查看它并知道我目前在做什么
ReynierPM

1
@HardeepSingh两者:ENV(stackoverflow.com/a/33836848/6309)和ARG(stackoverflow.com/a/41593407/6309
VonC

0

因此,如果要将每个构建的环境变量的值设置为不同的值,则可以在构建时传递这些值,而无需每次都更改docker文件。

ENV,一旦设置,将无法通过命令行值覆盖。因此,如果我们希望我们的环境变量在不同的构建中具有不同的值,那么我们可以ARG在docker文件中使用并设置默认值。而且,当我们想要覆盖这些值时,我们可以--build-args在每次构建时都使用它,而无需更改我们的docker文件。

有关更多详细信息,可以参考this

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.