Представьте, что у нас есть такой файл .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.
Итак, похоже, что он вообще не заменяет переменную. Как мне тогда поступить?
@Wyck, да, ты прав. Дело в том, что я просто хотел показать, что я пытаюсь как-то это сделать, и это не работает (потому что я делаю это неправильно), и я хочу знать, как это сделать правильно, если это возможно. Ни $(()), ни ${}, ни $() не работают.
Я пытаюсь что-то вроде /bin/bash -c "SOME_CACHE_VAR=((100)) my-service"
, но у меня пока нет правильного синтаксиса. Но стратегия, которую я изучаю, состоит в том, чтобы заменить команду службы командой bash, которая выполняет подстановки, а затем запускает службу. Может быть, кто-то другой разберется раньше меня.
Кстати, VAR_B = ${VAR_A}
«работает», поскольку это правильный синтаксис замены. Это просто не делает арифметику. Вы получаете только замену, конкатенацию и образования ${variable:-word}
и ${variable:+word}
.
@Wyck спасибо за ваше время. Проблема в том, что мне нужны эти преобразования в файле .env. Когда я делаю это: VAR_B=${VAR_A} там, а в разделе 'environment' файла docker-compose это: JUST_VAR: ${VAR_B}, затем я запускаю систему, вхожу в контейнер docker, запускаю команду 'env ' и, наконец, получите это: JUST_VAR=${VAR_A}, а не точное значение. Итак, это проблема, которую я пытаюсь решить, и, возможно, ответ заключается в том, что вы не можете подставлять переменные в файл .env, idk.
Будут ли эти расчеты всегда исправлены? Вы ожидаете, что VAR_A
будет настраиваемым, но приложению необходимо, чтобы SOME_CACHE_VAR
было установлено на половину его значения, и вы бы не стали независимо устанавливать VAR_B
или VAR_MEM
?
FWIW, я не вижу того, что видите вы: замена (без арифметики) отлично работает для меня. У меня есть замена JUST_VAR: ${VAR_B}
в файле docker-compose.yml, а также у меня есть и VAR_B=${VAR_A}
, и VAR_A=123
в файле .env, а в файле dockerfile есть CMD [ "env" ]
, и команда env
правильно отображает, что JUST_VAR
имеет значение 123
. Может быть, вам стоит опубликовать свои файлы дословно? Может проблема в синтаксисе. (ПРИМЕЧАНИЕ: я понимаю, что вы ищете арифметическое решение для .env, но механизм подстановки докеров не выполняет математику. Все еще ищет решение для вас.)
@DavidMaze Результат расчета будет зависеть от количества устройств в нашей системе. Итак, есть одна переменная, значение которой можно менять, и это должно влиять на другие переменные.
@Wyck странно... Для меня это напечатало JUST_VAR=${VAR_A}, может быть, у меня была опечатка, но я уверен, что перепроверил все, прежде чем писать здесь свой ответ. Кстати, из-за крайнего срока я нашел решение, которое искал. Я только что написал скрипт Python, который читает файл .env
, получает значение переменной, от которой зависят остальные, выполняет все вычисления и генерирует новые значения для других переменных. Сразу после этого докер запускает все свои контейнеры, и я получаю внутри нужные мне значения. Возможно, это не лучшее решение, но... по крайней мере, оно работает... И еще раз спасибо за ваше время.
Если фактические расчеты фиксированы и есть только одно настраиваемое значение, вы можете выполнить расчет внутри контейнера, вместо того, чтобы пытаться настроить его на уровне 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
Как вы думаете, что делает синтаксис
$((xxx))
доллара в двойных скобках в файле .env для создания докеров? (Потому что я почти уверен, что он не делает то, что вы думаете/надеетесь, что он делает.)