SSH 是系统管理员工具箱中最常用的命令之一,但在 Docker 中并不常见。以下是如何通过 SSH 连接到正在运行的容器以及为什么在此之前应该三思而后行。
您应该将 SSH 与 Docker 容器一起使用吗?
SSH 连接到 Docker 容器通常是一种不好的做法,您应该避免。使用该docker exec
命令在容器内获取 shell几乎总是更好。
Docker 新手可能会尝试使用 SSH 来更新容器内的文件。容器是一次性的,因此它们在创建后应该被视为不可变的,除了存储在卷中的持久数据。编辑源代码时,创建一个新映像并重新启动容器。
除了多步配置过程之外,在 Docker 镜像中安装 SSH 会添加几个依赖包并暴露另一个潜在的攻击向量。在具有多个活动容器的系统上,您将运行多个独立的 SSH 进程,并且必须记住每个容器的正确端口。
不要将 SSH 添加到单个容器,而是在运行 Docker 的物理主机上安装一次。使用 SSH 连接到您的主机,然后运行docker exec -it my-container bash
以访问单个容器。
虽然docker exec
SSH 是首选方法,但仍有一些场景可能会用到 SSH。您可以将其引入作为与遗留部署系统集成的权宜之计。它也可能被一些 IDE 和构建工具用于在开发过程中提供实时重新加载功能。
在 Docker 容器中安装 SSH 服务器
大多数流行的 Docker 基础镜像都被有意简化。您需要自己添加 OpenSSH 服务器,即使是在源自流行操作系统发行版的映像上也是如此。
以下是Dockerfile
基于 Debian 的映像的示例:
运行 apt-get update && apt-get install -y openssh-server
运行 sed -i 's/PermitRootLogin 禁止密码/PermitRootLogin yes/' /etc/ssh/sshd_config
入口点服务 ssh start && bash
SSH 配置已修改,因此您可以root
以 Docker 容器中的默认用户身份登录。为了提高安全性,请改为设置专用用户帐户:
运行 useradd -m -s /bin/bash sshuser
这将创建一个sshuser
使用主目录 ( -m
)调用的新用户。该-s
开关将用户的默认登录 shell 设置为 Bash。
使用ENTRYPOINT
可确保 SSH 服务始终在容器启动时启动。然后将执行交给 Bash 作为容器的前台进程。您可以将其替换为应用程序的二进制文件。
配置认证
接下来,您需要设置身份验证系统。您可以为您的sshuser
帐户分配一个密码并使用该密码登录:
运行 echo "sshuser:Changeme" | 更改密码
更安全的方法是设置 SSH 密钥身份验证。您需要在客户端计算机上创建一个密钥对,然后将公共部分复制到容器中。通过这种方式,SSH 守护进程可以在您连接时验证您机器的身份。
更改您为您的用户Dockerfile
设置.ssh
配置文件夹。复制从您的工作目录中的公钥,无论是与一个docker cp
命令或COPY
指令中Dockerfile
。在后一种情况下,密钥将被烘焙到图像中,任何有权访问的人都可以看到。
复制 id_rsa.pub /home/sshuser/.ssh/authorized_keys
运行 chown -R sshuser:sshuser /home/sshuser/.ssh
运行 chmod 600 /home/sshuser/.ssh/authorized_keys
这一系列命令在您的工作目录中使用公钥创建 SSHauthorized_keys
文件id_rsa.pub
。调整文件系统权限以符合 SSH 的要求。
连接到容器
现在您已准备好连接到您的容器。运行容器,将端口 22 绑定到主机:
docker run -p 22:22 my-image:latest
运行ssh sshuser@example.com
会给你一个容器内的外壳。
如果要从托管 Docker 容器的机器进行连接,则可以跳过绑定端口。使用docker inspect
让您的容器的IP地址,然后将它传递到SSH连接命令。
码头工人检查 <id 或名称> | grep 'IP 地址' | 头-n 1
使用您机器上的 SSH 客户端连接到容器:
ssh 根@172.17.0.1
# 或
ssh sshuser@172.17.0.1
如果您在主机上运行单独的 SSH 服务器,或者您有多个需要端口 22 的容器,则需要使用备用端口。 以下是当 SSH 绑定到端口 2220 时如何启动连接:
docker run -p 22:2220 my-image:latest
ssh 根@172.17.0.1 -p 2220
使用 SSH 配置设置容器快捷方式
您可以操作 SSH 配置文件以简化与单个容器的连接。编辑~/.ssh/config
以定义具有预配置端口的速记主机:
托管我的容器
主机名 172.17.0.1
2220端口
用户 sshuser
现在您可以运行ssh my-container
以直接放入您的容器中。这使得在不记住容器 IP 和端口的情况下更容易处理多个连接。
使用 Dockssh 来简化容器管理
该Dockssh项目通过提供另一个守护,让您运行进一步采取这样的步骤ssh my-container@example.com
,不需要任何手动配置SSH。您不需要在容器中安装 SSH 服务器;Dockssh 会自动代理 SSH 连接并运行正确的docker exec
命令。
必须先安装Redis来存储Dockssh的配置数据:
sudo apt 安装 redis
接下来,通过添加包含容器名称和 SSH 连接密码的 Redis 记录来定义要公开的容器:
redis-cli 设置 dockssh:my-container:pass "container-password-here"
然后下载Dockssh:
须藤卷曲 https://github.com/alash3al/dockssh/releases/download/v1.1.0/dockssh_linux_amd64 -O /usr/local/bin/dockssh
须藤 chmod +x /usr/local/bin/dockssh
须藤 ufw 允许 22022
# 启动 DockSSH 服务器
码头
现在您可以连接到您的容器:
ssh 我的容器@example.com -p 22022
Dockssh 默认监听 22022 端口。打开防火墙以允许使用该端口的传入连接。
连接时,系统会提示您输入容器的密码。这是container-password-here
在我们上面的Redis记录中设置的。
使用 Dockssh 可以轻松通过 SSH 连接到大量 Docker 容器。当您定期从远程主机连接到容器时,这种方法非常理想,因为它将两步“SSH then docker exec
”序列简化为一个令人难忘的命令。
将 Dockssh 注册为系统服务以供长期使用:
须藤纳米 /etc/systemd/system/dockssh.service
[单位]
说明=Dockssh 服务
之后=网络.目标
[服务]
类型=简单
重启=总是
重启秒=1
用户=root
ExecStart=/usr/local/bin/dockssh
[安装]
WantedBy=multi-user.target
使用systemctl
以下方法启用服务:
须藤 systemctl 启用 Dockssh.service
须藤 systemctl 启动 Dockssh
Dockssh 现在将在您的系统启动时自动启动。
总结
将 SSH 与 Docker 容器相结合被广泛认为是一种反模式,但它仍然在开发、测试和遗留环境中使用。如果别无选择,您可以将 SSH 服务器添加到容器中,复制公钥,然后通过容器的 IP 或主机端口绑定进行连接。
想要远程管理大量 Docker 容器的系统管理员可以试用 Dockssh。它让您可以ssh
通过无缝的幕后映射来运行熟悉的命令docker exec
,使用未修改的图像为您提供两全其美的效果。