Dockerfile中的条件ENV

2w3kk1z5  于 2023-08-03  发布在  Docker
关注(0)|答案(8)|浏览(128)

是否可以根据构建ARG的值有条件地设置Dockerfile中的ENV变量?
例如:Something like

ARG BUILDVAR=sad
ENV SOMEVAR=if $BUILDVAR -eq "SO"; then echo "hello"; else echo "world"; fi

字符串
更新:当前使用基于马里奥的答案:

ARG BUILD_ENV=prod
ENV NODE_ENV=production
RUN if [ "${BUILD_ENV}" = "test" ]; then export NODE_ENV=development; fi


但是,使用--build-arg BUILD_ENV=test运行,然后转到主机上,我仍然会得到

docker run -it mycontainer bin/bash
[root@brbqw1231 /]# echo $NODE_ENV
production

qmelpv7a

qmelpv7a1#

是的,这是可能的,但你需要使用你的构建参数作为标志。您可以使用shell的参数扩展功能来检查条件。下面是一个概念验证的Docker文件:

FROM debian:stable
ARG BUILD_DEVELOPMENT
# if --build-arg BUILD_DEVELOPMENT=1, set NODE_ENV to 'development' or set to null otherwise.
ENV NODE_ENV=${BUILD_DEVELOPMENT:+development}
# if NODE_ENV is null, set it to 'production' (or leave as is otherwise).
ENV NODE_ENV=${NODE_ENV:-production}

字符串
测试构建:

docker build --rm -t env_prod ./
...
docker run -it env_prod bash
root@2a2c93f80ad3:/# echo $NODE_ENV 
production
root@2a2c93f80ad3:/# exit
docker build --rm -t env_dev --build-arg BUILD_DEVELOPMENT=1 ./
...
docker run -it env_dev bash
root@2db6d7931f34:/# echo $NODE_ENV
development

5f0d552i

5f0d552i2#

您不能直接在 Dockerfile 中运行bash代码,但必须使用RUN命令。例如,您可以使用RUN更改ENV并导出if中的变量,如下所示:

ARG BUILDVAR=sad 
RUN if [ "$BUILDVAR" = "SO" ]; \
    then export SOMEVAR=hello; \
    else export SOMEVAR=world; \
    fi

字符串
我没试过,但应该可以。

hzbexzde

hzbexzde3#

虽然你不能设置条件ENV变量,但你可以使用RUN命令和一个null-coalescing环境变量来完成你的任务:

RUN node /var/app/current/index.js --env ${BUILD_ENV:-${NODE_ENV:-"development"}}

字符串

3npbholx

3npbholx4#

你的逻辑其实是正确的。这里的问题是,RUN export ...在Dockerfile中无法工作,因为export命令不会跨映像持久化。Dockerfiles创建了一个临时容器来生成镜像,因此环境变量将不存在。
ENV另一方面,根据文档规定:
使用ENV设置的环境变量将在从结果映像运行容器时保持不变。
唯一的方法是在docker run命令中从镜像生成容器,并将逻辑 Package 在其周围:

if [ "${BUILD_ENV}" = "test" ]; then
    docker run -e NODE_ENV=development myimage
else
    docker run myimage
fi

字符串

oyt4ldly

oyt4ldly5#

如果我们只讨论环境变量,那么就用生产环境来设置它

ENV NODE_ENV prod

字符串
在开发的容器启动过程中,您可以使用-e NODE_ENV=dev
这种方式映像总是内置在生产中,但本地容器在开发中启动。

exdqitrt

exdqitrt6#

如果您只需要检查build-arg是否存在,并且希望设置默认值,则answer非常有用。为了改进这个解决方案,如果你想使用build-arg传递的数据,你可以执行以下操作:

FROM debian:stable
ARG BUILD_DEVELOPMENT=production
ENV NODE_ENV=$BUILD_DEVELOPMENT

字符串
神奇的是ARG的默认值。

pn9klfpd

pn9klfpd7#

将值传递到Dockerfile,然后传递到entrypoint脚本

从命令行传入所需的值(TARG)

docker run --env TARG=T1_WS01 -i projects/msbob

字符串
然后在你的Dockerfile中放入类似这样的内容

Dockerfile:
# if $TARG is not set then "entrypoint" defaults to Q0_WS01
CMD ./entrypoint.sh ${TARG} Q0_WS01


entrypoint.sh脚本只读取第一个参数

entrypoint.sh:
#!/bin/bash
[ $1 ] || { echo "usage: entrypoint.sh <$TARG>" ; exit ; }
target_env=$1

ubbxdtey

ubbxdtey8#

我在容器上设置代理服务器时遇到了类似的问题。
我使用的解决方案是一个入口点脚本和另一个用于环境变量配置的脚本。使用RUN可以确保配置脚本在构建时运行,而在运行容器时使用ENTRYPOINT。
--build-arg用于命令行设置代理用户和密码。
入口点脚本如下所示:

#!/bin/bash
# Load the script of environment variables
. /root/configproxy.sh
# Run the main container command
exec "$@"

字符串
configproxy.sh

#!/bin/bash

function start_config {
read u p < /root/proxy_credentials

export HTTP_PROXY=http://$u:$p@proxy.com:8080
export HTTPS_PROXY=https://$u:$p@proxy.com:8080

/bin/cat <<EOF > /etc/apt/apt.conf 
Acquire::http::proxy "http://$u:$p@proxy.com:8080";
Acquire::https::proxy "https://$u:$p@proxy.com:8080";
EOF
}

if [ -s "/root/proxy_credentials" ]
then
start_config
fi


在Dockerfile中,配置:

# Base Image
FROM ubuntu:18.04

ARG user
ARG pass

USER root

# -z the length of STRING is zero
# [] are an alias for test command
# if $user is not empty, write credentials file
RUN if [ ! -z "$user" ]; then echo "${user} ${pass}">/root/proxy_credentials ; fi

#copy bash scripts
COPY configproxy.sh /root
COPY startup.sh .

RUN ["/bin/bash", "-c", ". /root/configproxy.sh"]

# Install dependencies and tools
#RUN apt-get update -y && \
#    apt-get install -yqq --no-install-recommends \
#    vim iputils-ping

ENTRYPOINT ["./startup.sh"]
CMD ["sh", "-c", "bash"]


生成时不使用代理设置

docker build -t img01 -f Dockerfile .


使用代理设置生成

docker build -t img01 --build-arg user=<USER> --build-arg pass=<PASS> -f Dockerfile .


看看here

相关问题