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

这可能是一个微不足道的问题,但是阅读 ARGENV的文档并不能让我清楚地理解这些问题。

我正在构建一个 PHP-FPM 容器,我希望能够根据用户需要启用/禁用一些扩展。

如果在 Dockerfile 可以通过在 build 命令中添加条件和传递标志来实现这一点,那就太好了。

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

#!/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吗?

我是开放的想法,如果你有一个不同的方法来实现这一点,请让我知道它

147503 次浏览

来自 Dockerfile 引用:

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

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

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

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

考虑到所涉及的组合数量,在运行时使用 ENV设置这些特性是最好的。

但是你可以通过以下方式进行 两者结合:

  • 构建具有特定 ARG的图像
  • 使用 ARG作为 ENV

也就是说,Dockerfile 包括:

ARG var
ENV var=${var}

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

因此,如果想为每次构建都设置不同的环境变量值,那么我们可以在构建期间传递这些值,而不需要每次都更改 docker 文件。

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

有关详细信息,请参阅 这个