对docker build感到困惑,以便永远保持运行docker container

时间:2018-04-30 11:14:25

标签: linux docker

所以,我第一次玩Docker。我所做的是在容器上运行一个Open SSH服务器,以便我可以从任何地方登录它。当我将以下内容用于docker build时,它工作正常。已在基本映像中安装了打开的SSH服务器。

#Download base image
FROM BaseImage
RUN mkdir /var/run/sshd
CMD ["/usr/sbin/sshd", "-D"]

如果我使用以下

运行容器
docker run -p 52022:22 -dit <MyContainerID>

从外面登录,就像这样,

ssh -p 52022 <userName>@<IPAddress>

我可以登录。

但后来我将docker文件更改为更通用的东西,将下一个命令替换为下面显示的内容,因为我从互联网上读到CMD tail -f /dev/null是一种保持docker容器运行的方法。

CMD service ssh start
CMD tail -f /dev/null

但是,现在如果我尝试从外部登录,我会收到以下错误。

ssh_exchange_identification: Connection closed by remote host

是什么原因?为什么这不起作用。命令service ssh start应该在后台启动SSH服务器,不是吗?

3 个答案:

答案 0 :(得分:0)

好的,我解决了这个问题。在docker中,您只需使用一次CMD即可。所以,而不是

CMD service ssh start
CMD tail -f /dev/null

应该是,

CMD service ssh start && \
    tail -f /dev/null

答案 1 :(得分:0)

问题是Docker构建指令只考虑了最后一次CMD 所以你需要将两个CMD合并为一个命令。

答案 2 :(得分:0)

我想我会稍微澄清一下这里的情况。关于如何使用CMD指令以及ENTRYPOINT,我认为你应该考虑在这里使用。

Dockerfile中的CMDENTRYPOINT指令帮助我们指定在启动映像时应该运行的命令,以及它应该接收的参数。

通常,您要做的是让ENTRYPOINT指定应该调用的可执行文件或脚本。通常的做法是在此处添加entrypoint.shdocker-entrypoint.sh脚本。

然后使用CMD命令指定入口点脚本的参数。

因此,对于ENTRYPOINT ["ping"]CMD ["localhost"],容器将以命令ping localhost开头。

来自docker documentation

  

CMD的主要目的是为执行提供默认值   容器

因此,对于您的实例,我会使用:CMD ["/usr/sbin/sshd", "-D"] - 如果您需要在启动时向容器发送任何其他内容,请创建一个接受这些参数的入口点脚本,将脚本设置为ENTYPOINT并在它结束时开始流程/usr/sbin/sshd -D

我相信你可能会试图在这里删除你的sshd日志,以便将它传送到stdout和stderr。使用sshd的-D标志,您的进程将不会成为守护进程,而是保持在执行它的会话的前台。而对于docker,这正是您想要的。 Docker正在记录发送到stdout和stderr的所有内容,并且您想要使用它。如果您的sshd进程尚未登录到stdout和stderr,那么您可以将其配置为在Dockerfile中执行此操作。

我建议你阅读这篇文章,了解你在做什么:Dockerize an SSH service