我有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

当前回答

# 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:版本号。

其他回答

在可能的情况下,不要使用其他答案中描述的构建参数。这是一个古老的混乱的解决方案。Docker的target属性解决了这个问题。

目标的例子

Dockerfile

FROM foo as base

RUN ...

# Build dev image
FROM base as image-dev

RUN ...
COPY ...

# Build prod image
FROM base as image-prod

RUN ...
COPY ...
docker build --target image-dev -t foo .
version: '3.4'

services:

  dev:
    build:
      context: .
      dockerfile: Dockerfile
      target: image-dev

现实世界中

dockerfile在现实世界中变得很复杂。使用buildkit & COPY——from可以获得更快、更可维护的dockerfile:

Docker在目标之上构建每个阶段,而不管它是否被继承。使用buildkit只构建继承的阶段。Docker必须是v19+。希望这很快会成为默认功能。 目标可以共享构建阶段。使用COPY——from来简化继承。

FROM foo as base
RUN ...
WORKDIR /opt/my-proj

FROM base as npm-ci-dev
# invalidate cache
COPY --chown=www-data:www-data ./package.json /opt/my-proj/package.json
COPY --chown=www-data:www-data ./package-lock.json /opt/my-proj/package-lock.json
RUN npm ci

FROM base as npm-ci-prod
# invalidate cache
COPY --chown=www-data:www-data ./package.json /opt/my-proj/package.json
COPY --chown=www-data:www-data ./package-lock.json /opt/my-proj/package-lock.json
RUN npm ci --only=prod

FROM base as proj-files
COPY --chown=www-data:www-data ./ /opt/my-proj

FROM base as image-dev
# Will mount, not copy in dev environment
RUN ...

FROM base as image-ci
COPY --from=npm-ci-dev /opt/my-proj .
COPY --from=proj-files /opt/my-proj .
RUN ...

FROM base as image-stage
COPY --from=npm-ci-prod /opt/my-proj .
COPY --from=proj-files /opt/my-proj .
RUN ...

FROM base as image-prod
COPY --from=npm-ci-prod /opt/my-proj .
COPY --from=proj-files /opt/my-proj .
RUN ...

开启实验模式。

sudo echo '{"experimental": true}' | sudo tee /etc/docker/daemon.json

启用buildkit进行构建。Buildkit默认构建时不带缓存-启用——build-arg BUILDKIT_INLINE_CACHE=1

CI构建工作。

DOCKER_BUILDKIT=1 \
    docker build \
    --build-arg BUILDKIT_INLINE_CACHE=1 \
    --target image-ci\
    -t foo:ci
    .

使用——cache-from从拉出的图像中缓存

生产工作

docker pull foo:ci
docker pull foo:stage

DOCKER_BUILDKIT=1 \
    docker build \
    --cache-from foo:ci,foo:stage \
    --target image-prod \
    -t prod
    .

接受的答案可以解决这个问题,但是如果你想在dockerfile中有多行if条件,你可以把\放在每行的末尾(类似于你在shell脚本中的做法),并以;结尾每个命令。您甚至可以将set -eux之类的命令定义为第一个命令。

例子:

RUN set -eux; \
  if [ -f /path/to/file ]; then \
    mv /path/to/file /dest; \
  fi; \
  if [ -d /path/to/dir ]; then \
    mv /path/to/dir /dest; \
  fi

在你的情况下:

FROM centos:7
ARG arg
RUN if [ -z "$arg" ] ; then \
    echo Argument not provided; \
  else \
    echo Argument is $arg; \
  fi

然后使用:

docker build -t my_docker . --build-arg arg=42

# 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:版本号。

你可以添加一个简单的检查:

RUN [ -z "$ARG" ] \
    && echo "ARG argument not provided." \
    && exit 1 || exit 0

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

使用示例:

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

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