Замена переменной среды не работает в файле docker-compose

Представьте, что у нас есть такой файл .env:

VAR_A=300
VAR_B=$(($VAR_A/100))

VAR_MEM=$((50*$VAR_B))M

И мой файл docker-compose использует его следующим образом:

my-service:
  environment:
    SOME_CACHE_VAR: ${VAR_MEM:-100M}

Когда я запускаю docker-compose, он выдает ошибку:

docker.errors.DockerException: Failed converting the string value for memory ($((50*$VAR_B))) to an integer.

Итак, похоже, что он вообще не заменяет переменную. Как мне тогда поступить?

Как вы думаете, что делает синтаксис $((xxx)) доллара в двойных скобках в файле .env для создания докеров? (Потому что я почти уверен, что он не делает то, что вы думаете/надеетесь, что он делает.)

Wyck 10.12.2020 05:40

@Wyck, да, ты прав. Дело в том, что я просто хотел показать, что я пытаюсь как-то это сделать, и это не работает (потому что я делаю это неправильно), и я хочу знать, как это сделать правильно, если это возможно. Ни $(()), ни ${}, ни $() не работают.

insotriplesix 10.12.2020 06:08

Я пытаюсь что-то вроде /bin/bash -c "SOME_CACHE_VAR=((100)) my-service", но у меня пока нет правильного синтаксиса. Но стратегия, которую я изучаю, состоит в том, чтобы заменить команду службы командой bash, которая выполняет подстановки, а затем запускает службу. Может быть, кто-то другой разберется раньше меня.

Wyck 10.12.2020 06:16

Кстати, VAR_B = ${VAR_A} «работает», поскольку это правильный синтаксис замены. Это просто не делает арифметику. Вы получаете только замену, конкатенацию и образования ${variable:-word} и ${variable:+word}.

Wyck 10.12.2020 06:43

@Wyck спасибо за ваше время. Проблема в том, что мне нужны эти преобразования в файле .env. Когда я делаю это: VAR_B=${VAR_A} там, а в разделе 'environment' файла docker-compose это: JUST_VAR: ${VAR_B}, затем я запускаю систему, вхожу в контейнер docker, запускаю команду 'env ' и, наконец, получите это: JUST_VAR=${VAR_A}, а не точное значение. Итак, это проблема, которую я пытаюсь решить, и, возможно, ответ заключается в том, что вы не можете подставлять переменные в файл .env, idk.

insotriplesix 10.12.2020 07:21

Будут ли эти расчеты всегда исправлены? Вы ожидаете, что VAR_A будет настраиваемым, но приложению необходимо, чтобы SOME_CACHE_VAR было установлено на половину его значения, и вы бы не стали независимо устанавливать VAR_B или VAR_MEM?

David Maze 10.12.2020 12:36

FWIW, я не вижу того, что видите вы: замена (без арифметики) отлично работает для меня. У меня есть замена JUST_VAR: ${VAR_B} в файле docker-compose.yml, а также у меня есть и VAR_B=${VAR_A}, и VAR_A=123 в файле .env, а в файле dockerfile есть CMD [ "env" ], и команда env правильно отображает, что JUST_VAR имеет значение 123. Может быть, вам стоит опубликовать свои файлы дословно? Может проблема в синтаксисе. (ПРИМЕЧАНИЕ: я понимаю, что вы ищете арифметическое решение для .env, но механизм подстановки докеров не выполняет математику. Все еще ищет решение для вас.)

Wyck 10.12.2020 16:42

@DavidMaze Результат расчета будет зависеть от количества устройств в нашей системе. Итак, есть одна переменная, значение которой можно менять, и это должно влиять на другие переменные.

insotriplesix 16.12.2020 08:29

@Wyck странно... Для меня это напечатало JUST_VAR=${VAR_A}, может быть, у меня была опечатка, но я уверен, что перепроверил все, прежде чем писать здесь свой ответ. Кстати, из-за крайнего срока я нашел решение, которое искал. Я только что написал скрипт Python, который читает файл .env, получает значение переменной, от которой зависят остальные, выполняет все вычисления и генерирует новые значения для других переменных. Сразу после этого докер запускает все свои контейнеры, и я получаю внутри нужные мне значения. Возможно, это не лучшее решение, но... по крайней мере, оно работает... И еще раз спасибо за ваше время.

insotriplesix 16.12.2020 08:43
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
1
10
1 213
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если фактические расчеты фиксированы и есть только одно настраиваемое значение, вы можете выполнить расчет внутри контейнера, вместо того, чтобы пытаться настроить его на уровне Compose. Напишите сценарий оболочки для вычисления этих значений, затем запустите основной процесс контейнера:

#!/bin/sh
if [ -n "$VAR_A" ]; then
  VAR_B=$(($VAR_A/100))
  SOME_CACHE_VAR=$((50*$VAR_B))M
else
  SOME_CACHE_VAR=100M
fi
export SOME_CACHE_VAR
exec "$@"

Скопируйте этот скрипт в свой образ и сделайте его точкой входа в образ.

COPY entrypoint.sh ./
RUN chmod +x entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]
CMD (as before)

Теперь, когда вы запускаете контейнер, вам нужно предоставить $VAR_A, но не какие-либо производные переменные. Изображение CMD или все, что вы переопределяете с помощью Compose command:, будет запускаться с правильным вычислением $SOME_CACHE_VAR.

docker run --rm -e VAR_A=1000 my-image sh -c 'echo $SOME_CACHE_VAR'
# Should print "500M"

Вычисленное значение не будет отображаться в инструментах отладки, таких как docker inspect или docker exec, но основной процесс-контейнер все равно увидит его.

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

my-service:
  environment:
    - SOME_CACHE_VAR

И вы можете запустить тот же самый сценарий для вычисления значения перед вызовом Compose.

./entrypoint.sh docker-compose up

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