Я хочу добавить том в свою службу, но только если конечный пользователь предоставил для него папку. В противном случае монтировать том не следует, поскольку уже подготовленный образ содержит действительные данные в папке по умолчанию.
То есть я хочу сделать что-то вроде (псевдокод):
services:
my_awesome_service:
volumes:
if ${VARIABLE} => ${VARIABLE}:/app/folder
Можно ли определить такие условные операторы в файле docker-compose?
Единственный способ сделать это возможным, как я вижу, - сначала определить базовый файл docker-compose, у которого нет монтирования тома, и вызов второго файла docker-compose, только если определен $VARIABLE. Это нормально для одного или нескольких условий, но неприятно, если их много.
Любое решение?


Да, я не думаю, что формат docker-compose поддерживает условные операторы.
Однако возможны два решения:
docker-compose.yaml:
command: ${COMMAND_PARAMS}
bash:
#!/bin/bash
if test -z $CONDITION; then
params = "-param1 ${MIPARAM1}"
else
params = "-param1 ${MIPARAM1} -param2 ${MIPARAM2}"
fi
COMMAND_PARAMS=$params docker-compose up
(кредиты принадлежат оригинальному постеру на github, @ shin-)
folder_defaults, затем всегда задавайте том в docker-compose.yml, но, наконец, добавьте внутренний скрипт в образ докера, который проверяет, пуста ли папка тома, и если да, то от ln -s к folder_defaults; в противном случае оставьте все как есть.Пример условного скрипта:
if [ -z "$(ls -A /a/folder)" ]; then
do something... using /a/folder_defaults
fi
Использование ls для проверки пути таким образом не делает различий между каталогом /a/folder и файлом с именем folder внутри каталога /a. Также -z выполняет then, если ls не нашел ни каталога, ни файла. Если вы хотите проверить, существует ли каталог или файл, то переключатель -n будет работать лучше, но самым простым способом было бы использовать -d, который проверяет, является ли путь существующим каталогом: if [ -d "/a/folder" ]; then. Также обратите внимание, что ваш код завершится ошибкой, если в пути есть пробел, потому что путь не указан (суб-оболочка есть, а путь внутри нее - нет)
Ничего подобного в настоящее время не существует. Варианты реализации этого, которые я могу придумать, включают:
Составьте множество частей файла и объедините части, необходимые для создания окончательного файла.
Динамически создавайте свой файл для создания сообщения. Что-то вроде jsonnet может быть хорошей отправной точкой.
Пропустите создание и просто динамически сгенерируйте свою команду docker run. Это начинает терять переносимость, но некоторые варианты использования проще написать самостоятельно.
Отправьте PR в репозитории github compose и docker / cli, чтобы расширить функциональность компоновки. Для меня было бы наиболее разумным сделать это с использованием синтаксиса шаблона golang.
закрытый вопрос, который я нашел по этой теме в docker compose issue github.com/docker/compose/issues/5756; учитывая, что условный оператор выходит за рамки :(
Если вы используете Rancher для оркестровки, есть доступные экранирования {{...}}, которые вы можете использовать для условных операторов в версии docker-compose от Rancher.
Подробнее об интегрированной системе шаблонов GO здесь.
Бедняжка:
volumes:
${VARIABLE:-/dev/null}:/app/folder
Или же:
volumes:
${VARIABLE:-/dev/null}:${VARIABLE:-/tmp}/app/folder
Как я раньше не знал о значениях env var по умолчанию? ? Это очень полезно не только для файлов docker-compose.
Это рискованное решение. 1. Ничто внутри контейнера не отличает /app/folder от любого обычного каталога. Сопоставление /app/folder с /dev/null хоста может вызвать некоторые проблемы. Например, Приложение-контейнер записывает или перемещает данные в /app/folder, ожидая, что данные будут сохранены, но будут потеряны. Более того, никакая обработка ошибок не сделает свое дело, потому что копирование или перемещение данных в /dev/null не вызывает никаких ошибок вообще. Поэтому даже приложение, в котором есть правильная обработка ошибок записи / перемещения, с радостью продолжит выполнение, как если бы все было сохранено в /app/folder.
2. Использование этого решения, когда контейнер запущен от имени пользователя root и особенно если он работает в привилегированном режиме, представляет собой потенциальный риск удаления /app/folder контейнера и, как следствие, /dev/null хоста, который, скорее всего, будет мешать работе хоста, см. Что мешает rm / dev / null. Однако, поскольку сопоставление /app/folder контейнера с /dev/null хоста выполняется докером-демоном, он может предотвратить это, чтобы гарантировать, что монтирование существует, но даже если это так, то кто обещал, что так будет всегда?
Здесь есть ответ, который объясняет, что делает синтаксис :-. TL; DR: указывает значение по умолчанию, которое будет использоваться, когда VARIABLE не определен.
Мы можем использовать условный оператор в файле docker-compose.yml, как показано ниже:
#jinja2: lstrip_blocks: True
version: "3.2"
services:
app-name:
image: url
deploy:
replicas: {{replication-num}}
resources:
limits:
memory: 4G
reservations:
memory: 1G
restart_policy:
condition: any
max_attempts: 3
update_config:
delay: 60s
failure_action: rollback
parallelism: 1
monitor: 30s
placement:
constraints:
- node.labels.node == worker
ports:
- "{{url}}:8000"
environment:
ps_environment: "{{env}}"
{% if env=='sandbox' %}
extra_hosts:
- {{ sandbox_fully }}
{% endif %}
secrets:
- source: pwdFile
labels:
- container_name=app-name
networks:
- App_External_Overlay
volumes:
- {{ dir }}:{{ dir }}
Это действительно круто, но я думаю, что он существует только в том случае, если вы используете дополнительное программное обеспечение, которое не является частью собственного docker-compose? Можете ли вы обновить это, чтобы включить полное решение?
Похоже, это может быть для SaltStack
@ScottSmith Очевидно, jinja-compose может запускать этот синтаксис. Хотя сам не тестировал.
Использование условных stmts в docker-compose в некоторой степени возможно. Оформить заказ подстановка переменных. Документация доступна только для простейшего из if-else. А поскольку я не пробовал использовать сложные выражения со строками, я не могу быть уверен. Но при проверке условных переменных следует помнить о следующих моментах:
env_file. Переменные в этом файле экспортируются в контейнер докеров перед переменными в параметре environment. Это означает, что переменные в environment переопределят переменные в env_file.
Я не думаю, что это возможно прямо в файле docker-compose (никогда не слышал об условном выражении в docker-compose), но вы могли бы запустить сценарий, который взял бы базовый docker-compose и добавил бы все необходимое перед запуском
docker-compose.