SSH进入运行中的Docker容器的2种方法

时间:2020-03-05 15:29:44  来源:igfitidea点击:

在本教程中,我们将研究如何在后台运行的Docker容器上获取bash shell。
它还将介绍如何在没有活动的控制台会话的情况下,将ssh放入在后台启动并保持运行状态的docker容器。

Docker的采用非常广泛,尤其是在微服务和开发领域。
大多数长时间运行的Docker容器没有活动的Shell控制台。
我们可能会按需连接到bash shell,例如:当我们想在终端上运行一些命令时。
替代方法是使用IP地址通过ssh到容器。

可以通过两种方式来获得在后台运行的容器的重击

1)使用docker exec命令

Docker引擎具有用于与容器交互的命令行工具docker。
命令选项exec用于在正在运行的容器中运行命令。
通过传递一些参数,我们应该能够获得bash会话。
使用的命令语法为:

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

下面是可以与此一起使用的选项的列表。

-d,--detach分离模式:在后台运行命令
-i,--interactive即使未连接STDIN仍保持打开状态
-t,--tty分配伪TTY
-u,--user字符串用户名或者UID(格式:<名称| uid> [:<group | gid>])
-w,--workdir字符串容器内的工作目录

我们的兴趣在于-t和-i选项,因为bash必须以交互方式运行。
让我们考虑一个例子来阐明这一点。

拉Nginx Docker镜像:

# docker pull nginx 
Using default tag: latestlatest: Pulling from library/nginx
f2aa67a397c4: Pull complete 3c091c23e29d: Pull complete 4a99993b8636: Pull complete 
Digest: sha256:0edf702c890e9518b95b2da01286509cd437eb994b8d22460e40d72f6b79be49Status: 
Downloaded newer image for nginx:latest

根据下载的docker镜像在后台启动测试容器。

# docker run --name nginx-bg -d nginx 
3bd76e19ad6ce2ff15657ebf4de4cc42eb503c55f608071a438de6ca709ba73b

这将从nginx docker镜像的后台启动一个名为nginx-bg的容器。
检查并确认容器正在运行:

Dockerps

现在运行以下命令以在该容器上获取bash控制台。

# docker exec -it nginx-bg /bin/bash
root@3bd76e19ad6c:/# apt-get update
Get:2 http://security.debian.org/debian-security stretch/updates InRelease [94.3 kB]
Ign:1 http://cdn-fastly.deb.debian.org/debian stretch InRelease 
Get:3 http://cdn-fastly.deb.debian.org/debian stretch-updates InRelease [91.0 kB]
Hit:4 http://cdn-fastly.deb.debian.org/debian stretch Release
Fetched 185 kB in 2s (83.4 kB/s) 
Reading package lists... Done

其中nginx-bg是容器名称,/bin/bash是容器上bash二进制文件的路径。
一旦在bash shell上执行了命令,就可以通过键入exit命令退出。

root@3bd76e19ad6c:/# exit

2)使用docker attach命令

docker exec的替代方法是docker attach。
语法是

# docker attach <container-name>

因此,在本例中,我们将运行:

# docker attach nginx-bg

默认情况下,这将使我们进入bash shell。

ssh到正在运行的容器中

如果要SSH到正在运行的Docker容器,则需要在/etc/hosts上配置的容器IP地址或者主机名或者网络中的有效DNS记录。

如果我们不知道容器的IP地址,则可以使用以下命令获取它:

export INSTANCE_NAME="nginx-bg"
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $INSTANCE_NAME

例子:

# export INSTANCE_NAME="nginx-bg"
# docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $INSTANCE_NAME
172.17.0.7

请注意,我们可以使用其ID替换容器名称。
我们得到的IP地址是172.17.0.7,请尝试ping它以查看是否响应。

# ping -c 2 172.17.0.7
PING 172.17.0.7 (172.17.0.7) 56(84) bytes of data.
64 bytes from 172.17.0.7: icmp_seq=1 ttl=64 time=0.107 ms
64 bytes from 172.17.0.7: icmp_seq=2 ttl=64 time=0.058 ms
--- 172.17.0.7 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.058/0.082/0.107/0.026 ms

我们需要先在容器上配置ssh,然后再对它运行ssh命令。
配置完成后,我们可以使用用户名和容器的IP地址SSH到它。

# ssh [email protected] 
[email protected]'s password: 
Linux 672175da3a51 3.10.0-693.17.1.el7.x86_64 #1 SMP Thu Jan 25 20:13:58 UTC 2016 x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@672175da3a51:~#

容器之间的无密码SSH

如果我们需要无密码身份验证,请在运行它时考虑将SSH公钥复制到该容器。
我不建议创建带有公共密钥的镜像,而是在具有所有公共密钥授权的主机系统上放置文件。

让我们创建一个文件:

# mkdir ~/container-ssh-keys
# vim  ~/container-ssh-keys/authorized_keys
# chmod 0600 ~/container-ssh-keys/authorized_keys

然后将公共SSH密钥添加到文件中,我们可以根据需要添加任意数量。
现在,当启动容器时,将此文件映射到容器上的/root/.ssh/authorized_keys,例如

# docker run --name mycon -it -v $HOME/container-ssh-keys/authorized_keys:/root/.ssh/authorized_keys \
ubuntu:16.04 /bin/bash

然后,我们应该能够使用私钥对从主机系统ssh复制复制的公钥,而无需提示输入密码。

# ssh root@container-ip