Как использовать переменную окружения Docker в массиве ENTRYPOINT?

Если я установлю переменную среды, скажем ENV ADDRESSEE=worldи я хочу использовать его в сценарии точки входа, объединенного в фиксированную строку, например:

ENTRYPOINT ["./greeting", "--message", "Hello, world!"]

с world как меняются ценности окружающей среды, как мне это сделать? Я пытался с помощью "Hello, $ADDRESSEE" но это, похоже, не работает, так как требует $ADDRESSEE в прямом смысле.

11 ответов

Решение

Вы используете exec-форму ENTRYPOINT. В отличие от формы оболочки, формаexec не вызывает командную оболочку. Это означает, что обычная обработка оболочки не происходит. Например, ENTRYPOINT [ "echo", "$HOME" ] не будет выполнять подстановку переменных в $HOME. Если вы хотите обработать оболочку, то либо используйте форму оболочки, либо выполните оболочку напрямую, например: ENTRYPOINT [ "sh", "-c", "echo $HOME" ],
При использовании формы exec и непосредственном выполнении оболочки, как в случае с формой оболочки, именно оболочка выполняет расширение переменной среды, а не docker (из ссылки на Dockerfile).

В вашем случае я бы использовал форму оболочки

ENTRYPOINT ./greeting --message "Hello, $ADDRESSEE\!"

После большой боли и огромной помощи со стороны @vitr и др. Я решил попробовать

  • стандартная замена bash
  • форма оболочки ENTRYPOINT (отличный совет сверху)

и это сработало.

ENV LISTEN_PORT=""

ENTRYPOINT java -cp "app:app/lib/*" hello.Application --server.port=${LISTEN_PORT:-80}

например

docker run --rm -p 8080:8080 -d --env LISTEN_PORT=8080 my-image

а также

docker run --rm -p 8080:80 -d my-image

оба установите порт правильно в моем контейнере

Refs

см. https://www.cyberciti.biz/tips/bash-shell-parameter-substitution-2.html

Я попытался решить с предложенным ответом и все еще столкнулся с некоторыми проблемами...

Это было решением моей проблемы:

ARG APP_EXE="AppName.exe"
ENV _EXE=${APP_EXE}

# Build a shell script because the ENTRYPOINT command doesn't like using ENV
RUN echo "#!/bin/bash \n mono ${_EXE}" > ./entrypoint.sh
RUN chmod +x ./entrypoint.sh

# Run the generated shell script.
ENTRYPOINT ["./entrypoint.sh"]

Конкретно ориентируясь на вашу проблему:
RUN echo "#!/bin/bash \n ./greeting --message ${ADDRESSEE}" > ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]

Что касается меня, я хотел сохранить имя скрипта в переменной и по-прежнему использовать форму exec.

Изначально я делал что-то вроде:

      ENTRYPOINT [ "${BASE_FOLDER}/scripts/entrypoint.sh" ]

Но, очевидно, это не сработало, потому что мы используем оболочку, а первая перечисленная программа должна быть исполняемым файлом на PATH. Чтобы исправить это, я сделал следующее:

      ENTRYPOINT [ "/bin/bash", "-c", "${BASE_FOLDER}/scripts/entrypoint.sh ${@}", "--" ]

Это позволяет нам принимать любые дополнительные аргументы, переданные в /bin/bash, и передайте те же аргументы нашему скрипту после того, как имя было разрешено с помощью bash.


человек 7 баш

-
A - сигнализирует об окончании опционов и отключает дальнейшую обработку опций. Любые аргументы после - рассматриваются как имена файлов и аргументы. Аргумент - эквивалентен -.

Я РЕШИЛ ЭТО ОЧЕНЬ ПРОСТО!

ВАЖНО: переменная, которую вы хотите использовать в ENTRYPOINT ДОЛЖЕН быть тип (а не тип).

ПРИМЕР №1:

      ARG APP_NAME=app.jar                    # $APP_NAME can be ARG or ENV type.
ENV APP_PATH=app-directory/$APP_NAME    # $APP_PATH must be ENV type.
ENTRYPOINT java -jar $APP_PATH

Это приведет к выполнению: java -jar app-directory/app.jar

ПРИМЕР №2 (ВАШ ВОПРОС):

      ARG ADDRESSEE="world"                       # $ADDRESSEE can be ARG or ENV type.
ENV MESSAGE="Hello, $ADDRESSEE!"            # $MESSAGE must be ENV type.
ENTRYPOINT ./greeting --message $MESSAGE

Это приведет к выполнению: ./greeting --message Hello, world!

  • Пожалуйста, проверьте, нужны ли вам кавычки "" при присвоении строковых переменных.

МОЙ СОВЕТ: Используйте ENV вместо того ARG по возможности, чтобы избежать путаницы с вашей стороны или SHELL боковая сторона.

В моем случае это работало так: (для приложения загрузки Spring в докере)

      ENTRYPOINT java -DidMachine=${IDMACHINE} -jar my-app-name

и передача параметров при запуске докера

      docker run --env IDMACHINE=Idmachine -p 8383:8383 my-app-name

В предыдущих ответах предлагается использовать форму оболочки. В моем случае это был не вариант, поскольку при его использовании сигналы не могут достичь самого процесса .

См. пункт 1 здесь https://hynek.me/articles/docker-signals/ .

Если бы синтаксис json мог разрешать переменные, я бы хотел именно этого:

      ENTRYPOINT ["${APP_NAME}"]

Если вы создадите файл для запуска следующим образом:

      RUN echo "#!/bin/bash \n ${APP_NAME}" > ./entrypoint.sh

Вы также потеряете сигналы, потому что будет создана новая оболочка.

См. пункт 2 и используйте exec

Окончательная форма, которая сработала для меня:

      RUN echo "#!/bin/bash \n exec ${APP_NAME}" > ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]

Я решил проблему, используя описанный выше вариант «создать собственный скрипт». Как это:

      FROM hairyhenderson/figlet
ENV GREETING="Hello"
RUN printf '#!/bin/sh\nfiglet -W \${GREETING} \$@\n' > /runme && chmod +x /runme
ENTRYPOINT ["/runme"]
CMD ["World"]

Беги как

      docker container run -it --rm -e GREETING="G'Day" dockerfornovices/figlet-greeter Alec

Если кто-то хочет пройти ARGили же ENVпеременную в исполняемую форму ENTRYPOINT, тогда может использоваться временный файл, созданный в процессе сборки образа.

В моем случае мне пришлось запускать приложение по-разному в зависимости от того, было ли приложение .NET опубликовано как автономное или нет. Что я сделал, так это создал временный файл и использовал его имя в ifзаявление моего скрипта bash.

Часть моего докерфайла:

      ARG SELF_CONTAINED=true #ENV SELF_CONTAINED=true also works
# File has to be used as a variable as it's impossible to pass variable do ENTRYPOINT using Exec form. File name allows to check whether app is self-contained
RUN touch ${SELF_CONTAINED}.txt
COPY run-dotnet-app.sh .
ENTRYPOINT ["./run-dotnet-app.sh", "MyApp" ]

run-dotnet-app.sh:

      #!/bin/sh

FILENAME=$1

if [ -f "true.txt" ]; then
   ./"${FILENAME}"
else
   dotnet "${FILENAME}".dll
fi

Вот что у меня сработало:

      ENTRYPOINT [ "/bin/bash", "-c", "source ~/.bashrc && ./entrypoint.sh ${@}", "--" ]

Теперь вы можете предоставить любые аргументы в docker run команда и по-прежнему читать все переменные среды.

Пришел сюда в поисках.envfileинформация дляdocker runкоманды и в итоге нашел ответ в другом месте, но решил поделиться с другими:

Это было ключом к пониманию синтаксиса .envfile:

Этот файл должен использовать синтаксис<variable>=value(который присваивает переменной заданное значение) или (который принимает значение из локальной среды) и # для комментариев.

Я нашел это по адресу https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file .

Другими словами, не делайтеVAR1=$SOME_OTHER_ENV_VAR

Другие вопросы по тегам