Я создаю контейнер Docker следующим образом:
$sudo docker build -t "logstash-collector" ~/logging/logstash/
$sudo docker run -d \
--user=root \
--name="logstash-collector-01" \
--net=logging \
--cap-add=NET_ADMIN \
logstash-collector
И оттуда я могу изменить его шлюз по умолчанию на контейнер nginx (для прозрачной балансировки нагрузки):
$sudo docker exec -it logstash-collector-01 ip route delete default
$sudo docker exec -it logstash-collector-01 ip route add default via 172.18.0.10
И работает, и все нормально:
$sudo docker exec -it logstash-collector-01 ip route
default via 172.18.0.10 dev eth0
172.18.0.0/16 dev eth0 proto kernel scope link src 172.18.0.3
Но когда я пытаюсь автоматизировать это, помещая эти команды в свой ~ / logging / logstash / Dockerfile, например:
FROM logstash
COPY logstash.conf /usr/local/share
CMD ["-f", "/usr/local/share/logstash.conf", "--config.reload.automatic"]
CMD ["ip", "route", "delete", "default"]
CMD ["ip", "route", "add", "default", "via", "172.18.0.10"]
Я вижу, как они выполняются во время сборки:
Но контейнер не запускается. sudo docker logs logstash-collector-01
говорит мне: RTNETLINK отвечает: файл существует
Эта ошибка возникает, если я выдаю второй ip route
команда без выдачи первой (Linux не будет добавлять маршрут, если он уже есть в его активной таблице маршрутизации). Но как это может быть? Не работают ли мои команды CMD в Dockerfile?
Это связано с тем, что вы можете указать только один CMD для каждого файла докеров.
CMD - это то, что будет запускать контейнер (обычно это logstash, длительный процесс, подобный демону), так что вы делаете только запущен последний CMD.
Вы можете рассмотреть решение lo-fi, такое как использование сети одного контейнера для совместного использования между nginx и агентами logstash, но тогда вам нужно будет отслеживать порты.
Выше по цепочке находятся такие решения, как кубернеты, которые упрощают подобные вещи.
Между тем вы можете обратиться к консулу (/ SkyDNS), чтобы помочь с обнаружением DNS.