Dockerfile, если условие else с внешними аргументами

У меня есть dockerfile

FROM centos:7
ENV foo=42

тогда я его построю

docker build -t my_docker .

и запустите его.

docker run -it -d  my_docker

Можно ли передавать аргументы из командной строки и использовать их с if else в файле Docker? Я имею в виду что-то вроде

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

и постройте с этим аргументом.

 docker build -t my_docker . --my_arg=42

Ответ 1

Это может выглядеть не так просто, но вы можете иметь свой файл Docker (условный) следующим образом:

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

а затем создайте изображение как:

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

или

docker build -t my_docker .

Ответ 3

По некоторым причинам, большинство ответов здесь не помогли мне (возможно, это связано с моим изображением FROM в Dockerfile)

Поэтому я предпочел создать bash script в своем рабочем пространстве в сочетании с --build-arg, чтобы обрабатывать оператор if при сборке Docker, проверяя, является ли аргумент пустым или нет

Скрипт 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:

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

Замечание: это перейдет к else (false) в скрипте bash

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

Замечание: это перейдет к if (true)

Изменить 1:

После нескольких попыток я нашел следующую статью и эту одну что помогло мне понять 2 вещи:

1) ARG перед FROM находится вне сборки

2) Оболочкой по умолчанию является /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 build:

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

Ответ 4

Просто используйте тестовый двоичный файл напрямую, чтобы сделать это. Вам также следует использовать команду noop ":", если вы не хотите указывать условие "else", чтобы docker не остановился с ошибкой, возвращающей ненулевое значение.

RUN test -z "$YOURVAR" || echo "var is set" && echo "var is not set"
RUN test -z "$YOURVAR" && echo "var is not set" || :
RUN test -z "$YOURVAR" || echo "var is set" && :

Ответ 5

Точно так же, как другие говорили, сценарий оболочки поможет.

Просто дополнительный случай, ИМХО, о котором стоит упомянуть (для кого-то, кто наткнулся здесь, ищет более простой случай), то есть Замена среды.

Переменные среды (объявленные с помощью оператора ENV) также могут использоваться в определенных инструкциях как переменные, которые должны интерпретироваться Dockerfile.

Синтаксис ${variable_name} также поддерживает несколько стандартных модификаторов bash, как указано ниже:

  • ${variable:-word} указывает, что если установлено variable, результатом будет это значение. Если variable не установлен, результатом будет word.

  • ${variable:+word} указывает, что если установлено variable, то результатом будет word, в противном случае результатом будет пустая строка.

Ответ 6

Использование скриптов Bash и Alpine/Centos

Dockerfile

FROM alpine  #just change this to centos 

ARG MYARG=""
ENV E_MYARG=$MYARG

ADD . /tmp
RUN chmod +x /tmp/script.sh && /tmp/script.sh

script.sh

#!/usr/bin/env sh

if [ -z "$E_MYARG" ]; then
    echo "NO PARAM PASSED"
else
    echo $E_MYARG
fi

Передача аргумента: docker build -t test --build-arg MYARG="this is a test" .

....
Step 5/5 : RUN chmod +x /tmp/script.sh && /tmp/script.sh
 ---> Running in 10b0e07e33fc
this is a test
Removing intermediate container 10b0e07e33fc
 ---> f6f085ffb284
Successfully built f6f085ffb284

Без аргументов: docker build -t test .

....
Step 5/5 : RUN chmod +x /tmp/script.sh && /tmp/script.sh
 ---> Running in b89210b0cac0
NO PARAM PASSED
Removing intermediate container b89210b0cac0
....

Ответ 7

Если вы хотите динамически создавать образы, то вы можете сделать это с помощью сценария сборки.

Docker уже предоставляет SDK для многих языков, которые обычно включают в себя вызов сборки, который позволяет вам указать произвольную строку или файл Docker для сборки.

Например, с Руби:

require 'docker'

val = my_arg == 42 ? "TRUE" : "FALSE"

# Create an Image from a Dockerfile as a String.
Docker::Image.build("FROM centos:7\nENV MY_ENV=" + val)