如何在Docker中间件容器A中自动通过SSH执行容器B、C的命令
原有思路的问题
你的思路存在SSH密钥认证逻辑颠倒的问题:SSH密钥认证是客户端(即容器A)持有私钥,服务端(即容器B、C)存储客户端的公钥即可完成认证,不需要容器A获取B、C的SSH密钥。另外使用sshpass传递密码的方案安全性低,也不符合无交互自动化的最佳实践。
正确实现方案
1. 预生成SSH密钥对
在宿主机执行以下命令生成无密码的SSH密钥对,全程无人工交互:
ssh-keygen -t ed25519 -f ./ssh_id -N ""
执行后会在当前目录生成两个文本格式的密钥文件:
ssh_id:私钥,后续给容器A使用ssh_id.pub:公钥,后续给容器B、C使用
2. 调整容器B、C的配置
2.1 修改Dockerfile
补充SSH服务相关配置,确保sshd服务正常运行、支持密钥登录:
FROM node RUN apt-get update RUN apt-get install -y openssh-server # 配置SSH服务允许root登录、开启密钥认证 RUN echo "PermitRootLogin yes" >> /etc/ssh/sshd_config && \ echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config && \ mkdir -p /root/.ssh && \ chmod 700 /root/.ssh COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh ENTRYPOINT ["sh", "/docker-entrypoint.sh"] WORKDIR /home/debian COPY ./ /home/debian RUN git init RUN git clone --branch master https://github.com/SamLProgrammer/LAB1SD.git WORKDIR /home/debian/LAB1SD RUN npm install CMD ["node", "index.js"]
2.2 修改docker-entrypoint.sh
确保启动时先运行sshd服务,再启动业务进程:
#!/bin/sh # 启动SSH服务 service ssh start # 修复公钥文件权限(避免权限过大导致SSH拒绝认证) chmod 600 /root/.ssh/authorized_keys # 启动主业务进程 exec "$@"
2.3 启动B、C容器时挂载公钥
运行容器时直接把预生成的公钥挂载到B、C的authorized_keys路径,不需要手动进入容器操作:
# 启动容器B示例 docker run -d -v ./ssh_id.pub:/root/.ssh/authorized_keys:ro <B镜像名> # 启动容器C示例 docker run -d -v ./ssh_id.pub:/root/.ssh/authorized_keys:ro <C镜像名>
3. 调整容器A的配置
3.1 修改Dockerfile
安装SSH客户端依赖:
FROM node RUN apt-get update # 安装SSH客户端 RUN apt-get install -y openssh-client WORKDIR /home/debian COPY ./ /home/debian RUN git init RUN git clone --branch another https://github.com/SamLProgrammer/DockerMiddlewareLab1.git WORKDIR /home/debian/DockerMiddlewareLab1 RUN npm install CMD ["node", "index.js"]
3.2 启动容器A时挂载私钥
运行容器时把预生成的私钥挂载到A的默认SSH私钥路径:
docker run -d -v ./ssh_id:/root/.ssh/id_ed25519:ro <A镜像名>
4. 调整A中的.sh脚本
添加SSH参数跳过主机密钥校验,避免首次连接弹出交互提示:
#!/bin/bash SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" # 执行B容器的远程命令 ssh $SSH_OPTS root@<B容器IP> "mkdir -p /path/to/dir && touch /path/to/dir/someFile.txt" # 执行C容器的远程命令 ssh $SSH_OPTS root@<C容器IP> "mkdir -p /path/to/dir && touch /path/to/dir/someFile.txt"
额外优化建议
如果使用docker-compose管理三个容器,可以直接将密钥配置为compose的secrets资源,不需要手动执行挂载命令,同时容器之间可以直接用服务名通信,不需要手动获取容器IP,自动化程度更高。
内容的提问来源于stack exchange,提问作者Clown
相关产品推荐
相关产品推荐

