Замена переменной среды не работает в файле 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.

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


1
1 213
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