所以,我第一次玩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服务器,不是吗?
答案 0 :(得分:0)
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中的CMD
和ENTRYPOINT
指令帮助我们指定在启动映像时应该运行的命令,以及它应该接收的参数。
通常,您要做的是让ENTRYPOINT
指定应该调用的可执行文件或脚本。通常的做法是在此处添加entrypoint.sh
或docker-entrypoint.sh
脚本。
然后使用CMD
命令指定入口点脚本的参数。
因此,对于ENTRYPOINT ["ping"]
和CMD ["localhost"]
,容器将以命令ping localhost
开头。
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