我创建了一个这样的 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 将不会添加路由)。但这怎么可能呢?我的 Dockerfile 的 CMD 命令处理是否乱序?
这是因为您只能为每个 dockerfile 指定一个 CMD。
CMD 是容器将运行的内容(通常是 logstash,一个长时间运行的类似守护进程的进程),所以你在做什么只是运行最后一个 CMD。
请参阅https://stackoverflow.com/questions/23692470/why-cant-i-use-docker-cmd-multiple-times-to-run-multiple-services#23693804
您可以考虑使用 lo-fi 解决方案,例如使用单个容器的网络在 nginx 和 logstash 代理之间共享,但是您需要跟踪端口。
更高的链条是像 kubernetes 这样的解决方案,它们使这种事情变得更容易。
在这两者之间,您可能会查看 consul(/SkyDNS) 以帮助进行 DNS 发现。