Dockerfile 中的“ip route”命令生成错误

Dockerfile 中的“ip route”命令生成错误

我创建一个这样的 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"]

我看到它们在构建期间被执行: Logstash 容器构建

但是容器启动失败。 sudo docker logs logstash-collector-01告诉我: RTNETLINK 回答:文件存在

如果我发出第二个ip route命令而不发出第一个命令,就会发生该错误(如果活动路由表中已经有路由,Linux 将不会添加路由)。但这怎么会这样?我的 Dockerfile 的 CMD 命令处理顺序是否乱了?

答案1

这是因为每个 dockerfile 只能指定一个 CMD。

CMD 是容器将要运行的(通常是 logstash,一个长期运行的守护进程),所以你正在做的是仅有的运行最后一个 CMD。

https://stackoverflow.com/questions/23692470/why-cant-i-use-docker-cmd-multiple-times-to-run-multiple-services#23693804

您可以考虑一种低保真解决方案,例如使用单个容器的网络在 nginx 和 logstash 代理之间共享,但随后您需要跟踪端口。

链条上层有像 kubernetes 这样的解决方案,可以使这种事情变得更容易。

在此期间,您可以研究 consul(/SkyDNS) 来帮助进行 DNS 发现。

相关内容