我创建一个这样的 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 命令处理顺序是否乱了?
答案1
这是因为每个 dockerfile 只能指定一个 CMD。
CMD 是容器将要运行的(通常是 logstash,一个长期运行的守护进程),所以你正在做的是仅有的运行最后一个 CMD。
您可以考虑一种低保真解决方案,例如使用单个容器的网络在 nginx 和 logstash 代理之间共享,但随后您需要跟踪端口。
链条上层有像 kubernetes 这样的解决方案,可以使这种事情变得更容易。
在此期间,您可以研究 consul(/SkyDNS) 来帮助进行 DNS 发现。