我有dockerfile

FROM centos:7
ENV foo=42

然后我建立它

docker build -t my_docker .

然后运行它。

docker run -it -d  my_docker

是否可以从命令行传递参数,并在Dockerfile中使用if else ?我的意思是

FROM centos:7
if (my_arg==42)
     {ENV=TRUE}
else:
     {ENV=FALSE}

用这个论证来构建。

 docker build -t my_docker . --my_arg=42

当前回答

根据docker build命令的文档,有一个名为——build-arg的参数。

使用示例:

docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .

在我看来,这正是你所需要的:)

其他回答

# FROM前面的ARGs用于图像 ARG IMLABEL=xxxx \ IMVERS = x.x 从$ {IMLABEL}: $ {IMVERS} # FROM后面的ARGs是用于脚本中使用的参数 ARG condition-x RUN if ["$condition-x" = "condition-1"];然后\ 回声“condition 1美元”;\ Elif ["$condition-x" = "condition-1"];然后\ 回声“情况2美元”;\ 其他的 回声“condition-others美元”;\ fi

build -t——build-arg IMLABEL——build-arg IMVERS——build-arg condition-x -f Dockerfile -t image:版本号。

出于某种原因,这里的大多数答案都没有帮助我(可能与Dockerfile中的From图像有关)

所以我更喜欢在我的工作空间中结合——build-arg创建一个bash脚本,以便在Docker构建时通过检查参数是否为空来处理if语句

Bash脚本:

#!/bin/bash -x

if test -z $1 ; then 
    echo "The arg is empty"
    ....do something....
else 
    echo "The arg is not empty: $1"
    ....do something else....
fi

Dockerfile:

FROM ...
....
ARG arg
COPY bash.sh /tmp/  
RUN chmod u+x /tmp/bash.sh && /tmp/bash.sh $arg
....

码头工人构建:

docker build --pull -f "Dockerfile" -t $SERVICE_NAME --build-arg arg="yes" .

注意:这将被用于bash脚本中的else (false)

docker build --pull -f "Dockerfile" -t $SERVICE_NAME .

备注:这将进入if (true)

编辑1:

经过几次尝试,我找到了下面的文章和这一篇 这让我明白了两件事:

1) FROM之前的ARG在构建之外

2)默认shell是/bin/sh,这意味着if else在docker构建中有一点不同。例如,你只需要一个“=”而不是“==”来比较字符串。

你可以在Dockerfile里面做这个

ARG argname=false   #default argument when not provided in the --build-arg
RUN if [ "$argname" = "false" ] ; then echo 'false'; else echo 'true'; fi

在docker构建中:

docker build --pull -f "Dockerfile" --label "service_name=${SERVICE_NAME}" -t $SERVICE_NAME --build-arg argname=true .

我在容器上设置代理服务器时遇到了类似的问题。

我使用的解决方案是一个入口点脚本和另一个环境变量配置脚本。使用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 . 

看看这里。

对于任何试图构建基于Windows的映像的人,您需要访问参数%%的cmd。

# Dockerfile Windows
# ...
ARG SAMPLE_ARG
RUN if %SAMPLE_ARG% == hello_world ( `
    echo hehe %SAMPLE_ARG% `
    ) else ( `
    echo haha %SAMPLE_ARG% `
)
# ...

顺便说一下,ARG声明必须放在FROM之后,否则参数将不可用。

我看到了很多可能的解决方案,但没有一个适合我今天面临的问题。所以,我正在花时间用另一个对我有用的可能的解决方案来回答这个问题。

在我的例子中,我利用了众所周知的if ["$VAR" == "this"];然后重复“do that”;fi。警告是Docker,我不知道为什么,在这种情况下不喜欢双等号。所以我们需要这样写if ["$VAR" = "this"];然后重复“do that”;fi。

这里有一个完整的例子,适用于我的情况:

FROM node:16

# Let's set args and envs
ARG APP_ENV="dev"
ARG NPM_CMD="install"
ARG USER="nodeuser"
ARG PORT=8080
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH=$PATH:/home/node/.npm-global/bin
ENV NODE_ENV=${APP_ENV}

# Let's set the starting point
WORKDIR /app

# Let's build a cache
COPY package*.json .
RUN date \
 # If the environment is production or staging, omit dev packages
 # If any other environment, install dev packages
 && if [ "$APP_ENV" = "production" ]; then NPM_CMD="ci --omit=dev"; fi \
 && if [ "$APP_ENV" = "staging" ]; then NPM_CMD="ci --omit=dev"; fi \
 && npm ${NPM_CMD} \
 && usermod -d /app -l ${USER} node

# Let's add the App
COPY . .

# Let's expose the App port
EXPOSE ${PORT}

# Let's set the user
USER ${USER}

# Let's set the start App command
CMD [ "node", "server.js" ]

因此,如果用户传递了正确的build参数,docker build命令将为生产应用创建一个映像。如果没有,它将创建一个带有dev Node.js包的应用程序映像。

为了让它工作,你可以这样调用:

# docker build --build-arg APP_ENV=production -t app-node .