Початок системного обслуговування з динамічного значення порту від Docker


5

Використовуючи CoreOS, Docker та systemd для управління своїми послугами, я хочу належним чином виконувати пошук послуг. Оскільки CoreOS використовує etcd (розподілений ключ-значення), для цього є дуже зручний спосіб. У системі ExecStartPost systemd я можу просто вставити розпочату послугу в etcd без проблем. У моєму шафі потрібно щось подібне:

ExecStartPost=/usr/bin/etcdctl set /services/myServiceName '{ \"host\": \"%H\", \"port\": 5555 }'

що працює як шарм.

Але тут виникла моя ідея. Docker має можливість випадковим чином призначити порт, якщо я просто запускаю, docker run -p 5555що є приголомшливим, оскільки мені не потрібно встановлювати його статично у файлі * .service, і я можу запустити кілька екземплярів на одному хості. Що робити, якщо я міг отримати випадково призначений порт і вставити замість статичного 5555?

Виявляється, я можу використовувати docker portкоманду, щоб отримати порт, і з деяким форматуванням ми можемо отримати просто порт

$(echo $(/usr/bin/docker port my-container-name 5555) | cut -d':' -f2)

що працює, якщо я встановив його (використовуючи bash) так:

/usr/bin/etcdctl set /services/myServiceName '{ \"host\": \"%H\", \"port\": '$(echo $(/usr/bin/docker port my-container-name 5555) | cut -d':' -f2)' }'

але за допомогою systemd я просто не можу змусити його працювати. Це код, який я використовую:

ExecStartPost=/usr/bin/etcdctl set /services/myServiceName '{ \"host\": \"%H\", \"port\": '$(echo $(/usr/bin/docker port my-container-name 5555) | cut -d':' -f2)'}'

Якось у мене щось не так, але важко налагодити, оскільки він працює під час набору в терміналі.


Тож у вас із цим пощастило? У мене дуже подібне питання. У мене навіть є формат Go, який працює в командному рядку, щоб динамічно утримувати порт, але не можу змусити його працювати у файлі Unit.
Pandalover

Дивіться мою відповідь нижче
gust1n

Відповіді:


2

Опція systemd ExecStartне робить інтерполяції оболонки і, таким чином, не розуміє подібні речі $(echo 'Hello'). Але, ви можете запустити оболонку, яка виконує команду, щоб отримати таку поведінку. Спробуйте щось на кшталт:

ExecStartPost=/bin/sh -c "/usr/bin/etcdctl set /services/myServiceName '{ \"host\": \"%H\", \"port\": '$(echo $(/usr/bin/docker port my-container-name 5555) | cut -d':' -f2)'}'"

0

Я в кінцевому рахунку використовував щось подібне:

ExecStart=/bin/sh -c "port=$(docker port [CONTAINER-NAME] [CONTAINER-EXPOSED-PORT] | cut -d ':' -f 2); echo Connected to $port, publishing to etcd...; while netstat -lnt | grep :$port >/dev/null; do etcdctl set /services/[CONTAINER-NAME]/[SOME-IDENTIFIER] $port --ttl 60 >/dev/null; sleep 45; done"

Але відповідь на моє запитання справді полягала в тому, що мені потрібно вказати, в якій оболонці виконувати команду.

Редагування: Додавання логіки шаблону Go

[Service]
EnvironmentFile=/etc/environment
ExecStartPre=/bin/sh -c "until docker port {{.Name}} {{.Port}} >/dev/null 2>&1; do echo Waiting for {{.Name}}; sleep 2; done; port=$(docker port {{.Name}} {{.Port}} | cut -d ':' -f 2); echo Waiting for $port/tcp...; until netstat -lnt | grep :$port >/dev/null; do sleep 1; done"
ExecStart=/bin/sh -c "port=$(docker port {{.Name}} {{.Port}} | cut -d ':' -f 2); echo Connected to $COREOS_PRIVATE_IPV4:$port/tcp, publishing to etcd...; while netstat -lnt | grep :$port >/dev/null; do etcdctl set /services/{{.Service}}/{{.Name}} $COREOS_PRIVATE_IPV4:$port --ttl 60 >/dev/null; sleep 45; done"
ExecStop=/usr/bin/etcdctl rm --recursive /services/{{.Service}}/{{.Name}}

Це зробить це, але я спеціально хочу це виправити за допомогою форматування шаблону Go, а не рядка команд.
Пандаловер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.