Я пытаюсь связать различные команды, чтобы автоматизировать общий процесс докера. Это не докер, это скорее попытка автоматизировать это в bash.
Я могу бегать:
docker ps | grep manager | cut -f -d ' '
Который перечисляет текущие контейнеры докеров, выделяет тот, который содержит слово «менеджер», а затем захватывает первое поле, которое является идентификатором контейнера, например, 3a5455f3ac72
Затем я могу запустить:
docker inspect -f'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}} 3a5455f3ac72
Который получает IP-адрес док-контейнера, например, 172.18.0.4
Чего я хотел бы добиться, так это переменной с именем container_id и переменной с именем container_IP, которые я могу использовать в сценариях bash. Я пытался:
container_id = "docker ps | grep manager | cut -f 1 -d ' '"
container_ip='docker inspect -f'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $container_id'
Но когда я пытаюсь создать переменную container_id, я получаю:
invalid argument "1" for "-f, --filter" flag: bad format of filter (expected name=value)
See 'docker ps --help'.
Я думаю, что у меня есть ошибка в том, как я использую одинарные/двойные кавычки, но я не могу понять, где я ошибаюсь.
Сохранение команд в переменных работает не очень хорошо; по сути, переменные предназначены для хранения данных, а не исполняемого кода. Вместо этого для хранения кода вам обычно нужна функция. См. BashFAQ #50: «Я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу!»
Во-первых, IP-адрес docker inspect почти бесполезен; он доступен только на одной конкретной настройке ОС хоста, и то только с того же хоста. Вы хотите вместо этого использовать опубликованный порт, который будет более переносимым и может вообще не требовать никаких docker команд?
@Fravadona Это замена команды. Замена процесса использует <(...) в качестве разделителей и действует как имя файла, содержимое которого поступает из стандартного вывода прилагаемой команды.
Почему $container_id' заканчивается одинарной кавычкой? Есть ли другие линии?
Вместо того, чтобы использовать docker ps для захвата container_id, почему бы не дать ему какое-нибудь известное имя, используя опцию -name при запуске вашего контейнера, а затем использовать это имя в команде inspect
Спасибо @anubhava - это многое упростило, и это работает. Хотя я постараюсь провести рефакторинг, основываясь на том, что сказал Гордон — код помещается в функции, а данные — в переменные.
Ваш код может выглядеть следующим образом:
container_id() {
docker ps -f 'name=manager' --format '{{.ID}}'
}
container_ip() {
local id
id=$(container_id)
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$id"
}
container_ip
ошибка в том, как я использую одинарные/двойные кавычки
Цитаты здесь не причем. Не храните команды в виде строк. Используйте функции для хранения команд. Не забудьте проверить свои скрипты с помощью shellcheck. Также смотрите http://mywiki.wooledge.org/BashFAQ/050 .
Создание переменных из конвейерных команд, содержащих одинарные кавычки
Чтобы создать переменные, выполните команды с подстановкой команд. Вместо функций можно просто выполнять команды:
container_id=$(docker ps | grep manager | cut -f 1 -d ' ')
container_ip=$(docker inspect -f'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container_id")
echo "$container_ip"
Первый конвейер команд, вероятно, следует преобразовать в одну команду docker ps -q --filter '...'; это должно улучшить как производительность, так и точность.
Спасибо за отличный ответ, который сработал для моего варианта использования. Затем я добавил sed -i 's/MANAGER_IP/'"$container_ip"'/g' file.txt, чтобы заменить общий заполнитель в файле.txt для идентификатора контейнера фактическим IP-адресом.
Вы можете использовать замены процессов, например. container_id = "$(docker ps | ...)", вместо буквальных строк для установки ваших переменных