当前位置: 首页 > 科技观察

为什么不需要在Docker容器中运行sshd

时间:2023-03-19 23:05:21 科技观察

当开始使用Docker时,人们经常会问“我如何进入容器?”其他人说“在你的容器中运行一个SSH服务器”。但是,正如您将从这篇博文中了解到的那样,您根本不需要运行SSHd守护进程来进入您的容器。当然,除非您的容器是SSH服务器。运行SSH服务器是一件很容易的事,因为它提供了一种进入容器的简单方法。我们公司几乎每个人都至少使用过一次SSH。我们中的很大一部分人每天都使用它,并且熟悉公钥与私钥、无密码登录、密钥代理,有时甚至使用端口转发和其他不太常见的功能。因此,人们建议您在容器内运行SSH也就不足为奇了。但是你应该仔细考虑。假设你假设有一个RedisServer或JavaWebservice的Docker镜像,我会问你以下问题:你需要使用SSH做什么?一般是想做备份,查看日志,或者重启进程,调整配置,也可以用gdb,strace之类的工具调试服务器。然后我们看看如何在不使用SSH的情况下完成这些事情。您如何管理密钥和密码?通常,您要么将它们写入您的图像,要么将它们放入一个卷中。您会考虑如果要更新这些密钥或密码,您会怎么做。如果将它们写入镜像,则需要重建镜像,重新部署它们,并重启容器。没关系,不是世界末日,但这绝不是一个宏伟的方法。将它们放在卷中,然后通过管理卷来管理它们比前者要好得多。这种方法有效,但有严重的缺点。您必须确保容器没有对该卷的写权限;否则,容器可能会破坏密钥(导致您以后无法进入容器),如果您与多个容器共享一个卷,情况会变得更糟。如果我们不使用SSH,我们是不是就少了一件需要担心的事情?您如何管理安全升级?SSH服务器是相当安全的,但仍然存在安全问题,如果需要,您将不得不使用SSH升级所有容器。这意味着大量的重建和重启。也就是说,即使你有一个简单的小型memcached服务,你仍然要确保及时的安全更新,否则千里之堤可能被一个蚁巢摧毁。所以还是那句话,如果不用SSH,岂不是少了一件操心的事?您需要“只安装一个SSH服务器”才能到达那里吗?当然不是。您需要安装进程管理器,例如Monit或Supervisor。这是因为Docker本身只会监控一个进程。如果需要运行多个进程,则必须添加一层可以监视它们的应用程序。换句话说,你把一个简单的问题复杂化了。如果您的应用程序停止(通常退出或崩溃),您必须从您的进程管理日志中检查它,而不是简单地检查Docker提供的信息。你可以负责将应用程序放入容器中,但你是否也应该负责管理访问策略和安全限制?在小型组织中,这些都不重要。但是在大型组织中,如果您是负责设置应用程序容器的人,那么很可能还有其他人负责定义远程访问策略。您的公司可能有严格的政策来定义谁可以访问、如何访问或其他各种审计跟踪要求。那样的话,你绝对不会被允许将SSH服务器扔到你的容器中。但是我该如何...备份我的数据?您的数据应该存在于卷中。然后您可以使用--volumes-from选项运行另一个与第一个容器共享该卷的容器。这样做的好处:如果你需要安装新的工具(如s75pxd)来长期保存你的备份数据,或者将数据转移到其他安全存储,你可以在这个特定的备份容器中而不是在主容器中进行服务容器。很整洁。检查日志?再次使用音量!如果你把所有的日志都写到一个特定的目录,而这个目录是一个卷,那么你可以启动另一个日志检查“容器(使用--volumes-from,记得吗?)并在那里做你需要做的事情。如果你仍然需要特殊的工具(或者只是一个有趣的ack-grep),你可以将它们安装在这个容器中,它保留了主容器的原始环境。重启服务?基本上所有服务都可以通过信号重启。当你使用/etc/init.d/foorestart或servicefoorestart,它们实际上会向进程发送一个特定的信号,你可以使用dockerkill-s来发送这个信号。一些服务可能不会监听这些信号,但可以接受特定套接字上的命令。如果是TCP套接字,只需要通过网络连接即可。如果是UNIX套接字,您可以再次使用卷。将容器和服务的控制套接字设置到一个特定的目录,这个目录就是一个volume。然后启动一个新的容器来访问这个卷;这样你就可以使用UNIX套接字了。“可是太复杂了!”-它不是。假设您名为foo的servcie在/var/run/foo.sock中创建了一个套接字,并要求您运行fooctlrestart以完成重启。只需使用-v/var/run(或在Docker文件中添加VOLUME/var/run)来启动服务。当你想重新启动时,使用--volumes-from选项并重新加载命令以启动相同的图像。像这样:#StartingtheserviceCID=$(dockerrun-d-v/var/runfooservice)#Restartingtheservicewithasidekickcontainerdockerrun--volumes-from$CIDfooservicefooctlrestart很简单!修改我的配置文件如果你正在执行持久化的配置更改,你***把他的更改放在镜像中,因为如果你再次启动一个容器,服务仍然会使用旧的配置,你的配置更改将会丢失。因此,您没有SSH访问权限!“但我需要在服务运行时更改我的配置;例如,添加一个新的虚拟站点!”在这种情况下,您需要使用...等待它...音量!配置应该在一个卷中,并且该卷应该与一个特殊用途的“配置编辑器”容器共享。您可以在此容器中使用您喜欢的任何东西:SSH+您最喜欢的编辑器,或接受API调用的Web服务,或从外部来源抓取信息的cron作业;任何。另外,关注点分离:一个容器运行服务,另一个容器处理配置更新。“但我做了临时更改,因为我正在测试不同的值!”在这种情况下,请查看下一节!调试我的应用程序?这可能是唯一需要进入容器的场景。因为您要运行gdb、strace、调整配置等。在这种情况下,您需要nsenter。介绍nsenternsenter是一个用于输入命名空间的小实用程序。从技术上讲,它可以进入一个现有的命名空间,或者在一组新的命名空间中生成一个进程。“什么是名称空间?”它们是容器的重要组成部分。简单地说:通过使用nsenter,您可以进入一个现有的容器,即使该容器没有运行ssh或任何特殊用途的守护进程。我从哪里得到nsenter?查看GitHub上的jpetazzo/nsenter。简单的安装是:dockerrun-v/usr/local/bin:/targetjpetazzo/nsenter它将nsenter安装到/usr/local/bin中,你可以马上使用它。nsenter在您的发行版中也可用(在util-linux包中)。如何使用?首先计算你要进入容器的PID:PID=$(dockerinspect--format{{.State.Pid}})然后进入容器:nsenter--target$PID--mount--uts--ipc--net--pid在容器中,可以运行shell解析器。如果您想以自动方式运行特定脚本或程序,请将其作为参数添加到nsenter。它的工作方式有点像chroot,只是它使用容器而不是简单的目录来工作。远程访问呢?如果需要从远程主机进入容器,有(至少)两种方法:SSH进入Docker主机并使用nsenter;SSH进入Docker主机并通过特殊的密钥参数(即nsenter)授权esenter命令。第一种方法比较简单;但需要对Docker主机的根访问权限(从安全角度来看不是很好)。第二种方法使用SSHauthorized_keys文件中的command=模式。您可能熟悉“经典的”authorized_keys文件,它看起来像这样:ssh-rsaAAAAB3N...QOID==jpetazzo@tarrasque(当然,真正的密钥很长,通常占用几行。)您还可以强制使用专有命令。如果你想在你的系统上查看远程主机上的可用内存,你可以使用SSH密钥,但你不想交出所有的shell权限,你可以在authorized_keys文件中输入以下内容:command="free"ssh-rsaAAAAB3N...QOID==jpetazzo@tarrasque现在,当使用专有密钥连接时,它可以执行free命令而不是获取shell。除此之外,别无他法。(通常,您可能还想添加no-port-forwarding;有关更多信息,请参阅authorized_keys(5)联机帮助页)。这种机制的关键是实现职责分离。Alice将服务放入容器中;她不必处理远程访问、登录等问题。Betty添加了一个SSH层,用于特殊情况(调试奇怪的问题)。夏洛特会考虑登陆。etc.总结在容器中运行SSH服务器,真的是错误(大写W)吗?老实说,没那么严重。当您无法访问Docker主机时,这甚至非常方便,但它仍然需要在容器内获取一个shell。另外,我们有很多种方法可以在容器中运行一个SSH服务器,并得到我们想要的所有特性,而且它的架构非常清晰。Docker允许您使用最适合您的工作流程。但是,在这样做之前,当快速进入“我的容器实际上是一个小型VPS”流行语的(上下文)时,请注意还有其他解决方案,以便您做出明智的决定。英文原文:WHYYOUDON'TNEEDTORUNSSHDINYOURDOCKERCONTAINERS翻译自:http://www.oschina.net/translate/why-you-dont-need-to-run-sshd-in-docker