Как использовать переменную окружения 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.
-
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