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 .
Ответ 2
В соответствии с build
командой документация существует параметр --build-arg
https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables-build-arg
Пример использования
docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .
ИМО это то, что вам нужно:)
Ответ 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)