如何 SSH 进入运行中的容器

SSH 可能不是在容器中运行命令的最佳方式;试试这个替代方案。
250 位读者喜欢这篇文章。
cubes coming together to create a larger cube

Opensource.com

容器改变了我们对虚拟化的看法。您可能还记得(或者可能仍然生活在)虚拟机是完整堆栈的日子,从虚拟化的 BIOS、操作系统和内核到每个虚拟化的网络接口控制器 (NIC)。 您登录到虚拟机的方式就像登录到您自己的工作站一样。 这是一个非常直接和简单的类比。

然后容器出现了,从 LXC 开始,最终发展成开放容器倡议 (OCI),事情开始变得复杂。

幂等性

在容器的世界中,“虚拟机”只在很大程度上是虚拟的。 所有不需要虚拟化的东西都从宿主机借用。 此外,容器本身通常被认为是短暂的和幂等的,因此它不存储持久数据,并且其状态由宿主机上的配置文件定义。

如果您习惯了旧的虚拟机方式,那么您自然希望登录到虚拟机以进行交互。 但是容器是短暂的,因此您在容器中所做的任何事情都会被遗忘,这是设计使然,如果容器需要重新启动或重新生成。

控制容器基础设施的命令(例如 oc, crictl, lxcdocker)提供了一个接口来运行重要的命令来重启服务、查看日志、确认重要文件的存在和权限模式等等。 您应该使用您的容器基础设施提供的工具与您的应用程序交互,或者编辑配置文件并重新启动。 这就是容器的设计目的。

例如,开源论坛软件 Discourse 官方以容器镜像的形式分发。 Discourse 软件是无状态的,因此它的安装包含在 /var/discourse 中。 只要您备份了 /var/discourse,您始终可以通过重新启动容器来恢复论坛。 容器不保存持久数据,其配置文件为 /var/discourse/containers/app.yml

如果您登录到容器并编辑它包含的任何文件,如果容器必须重新启动,所有更改都将丢失。

您从头开始构建的 LXC 容器更加灵活,配置文件(位于您定义的位置)在您启动容器时传递给容器。

Jenkins 这样的构建系统通常有一个默认的配置文件,例如 jenkins.yaml,它为基本容器镜像提供指令,该镜像仅用于构建和在源代码上运行测试。 构建完成后,容器就会消失。

现在您知道您不需要 SSH 才能与您的容器交互,这里概述了可用的工具(以及一些关于使用 SSH 的说明,尽管所有使它变得多余的精美工具)。

OpenShift Web 控制台

OpenShift 4 提供了一个用于容器创建和维护的开源工具链,包括一个交互式 Web 控制台。

当您登录到您的 Web 控制台时,导航到您的项目概览并单击 **Applications** 选项卡以获取 Pod 列表。 选择一个(正在运行的)Pod 以打开应用程序的 **Details** 面板。

Pod details in OpenShift

opensource.com

单击 **Details** 面板顶部的 **Terminal** 选项卡以在您的容器中打开一个交互式 Shell。

A terminal in a running container

opensource.com

如果您更喜欢基于浏览器的 Kubernetes 管理体验,您可以通过 learn.openshift.com 上的交互式课程了解更多信息。

OpenShift oc

如果您更喜欢命令行界面体验,您可以使用 **oc** 命令从终端与容器交互。

首先,获取正在运行的 Pod 列表(或参考 Web 控制台以获取活动 Pod 列表)。 要获取该列表,请输入

$ oc get pods

您可以查看资源(Pod、构建或容器)的日志。 默认情况下,**oc logs** 返回您指定的 Pod 中第一个容器的日志。 要选择单个容器,请添加 **--container** 选项

$ oc logs --follow=true example-1-e1337 --container app

您还可以查看 Pod 中所有容器的日志,使用

$ oc logs --follow=true example-1-e1337 --all-containers

执行命令

您可以使用以下命令远程执行命令

$ oc exec example-1-e1337 --container app hostname
	example.local

这类似于以非交互方式运行 SSH:您可以运行您想要运行的命令,而无需交互式 Shell 接管您的环境。

远程 Shell

您可以附加到正在运行的容器。 这仍然不会在容器中打开一个 Shell,但它确实直接运行命令。 例如

$ oc attach example-1-e1337 --container app

如果您需要在容器中获得一个真正的交互式 Shell,只要容器包含一个 Shell,您可以使用 **oc rsh** 命令打开一个远程 Shell。 默认情况下,**oc rsh** 启动 ** /bin/sh**

$ oc rsh example-1-e1337 --container app

Kubernetes

如果您直接使用 Kubernetes,您可以使用 **kubectl exec** 命令在您的 Pod 中运行一个 Bash Shell。

首先,确认您的 Pod 正在运行

$ kubectl get pods

只要列出了包含您的应用程序的 Pod,您就可以使用 **exec** 命令在容器中启动一个 Shell。 以 **example-pod** 作为 Pod 名称,输入

$ kubectl exec --stdin=false --tty=false 
  example-pod -- /bin/bash
root@example.local:/# ls
bin   core etc   lib    root  srv
boot  dev  home  lib64  sbin  tmp  var

Docker

**docker** 命令类似于 **kubectl**。 在 **dockerd** 守护进程运行时,获取正在运行的容器的名称(如果您不在相应的组中,您可能必须使用 **sudo** 来提升权限)

$ docker ps
CONTAINER ID    IMAGE       COMMAND      NAME
678ac5cca78e    centos     "/bin/bash"   example-centos

使用容器名称,您可以在容器中运行命令

$ docker exec example/centos cat /etc/os-release
CentOS Linux release 7.6
NAME="CentOS Linux"
VERSION="7"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
[...]

或者您可以启动一个 Bash Shell 进行交互式会话

$ docker exec -it example-centos /bin/bash

容器和设备

在处理云时,要记住的重要一点是,容器本质上是运行时,而不是虚拟机。 虽然它们与 Linux 系统有很多共同之处(因为它们 Linux 系统!),但它们很少直接转换为您可能在 Linux 工作站上开发的命令和工作流程。 但是,与设备一样,容器有一个界面可以帮助您开发、维护和监控它们,因此请熟悉前端命令和服务,直到您可以像与虚拟(或裸机)机器交互一样轻松地与它们进行交互。 很快,您会想知道为什么所有内容都没有开发为短暂的。

接下来阅读
标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。 他曾在电影和计算行业工作,通常同时进行。

6 条评论

我在 Linux 上进行图形设计。 我应该使用容器吗?

不一定,但您可能已经在使用 Flatpaks 或 Snaps,它们在很多方面都类似于容器。 例如,如果您安装了 GIMP 2.10.x,那么您可能将其安装为 Flatpak,因此它位于一个“沙箱”环境中,该环境在很大程度上借鉴了容器化模型的概念。

回复 by ClaraBDias

好文章

安全很重要,谢谢您的这篇文章

能够获得容器内的 root 权限也很重要。 对于 Docker,我建议添加 "-u0",如下所示
$ docker exec -it -u0 example-centos /bin/bash

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.