Docker容器内无法建立SSH隧道,公钥认证失败求助
容器内SSH公钥认证失败问题排查与解决
问题现象
宿主机直接运行Python SSH隧道程序可正常建立连接,但通过docker run --network=host test启动容器后,容器内程序及ssh -vvv命令均提示公钥认证失败,要求输入主机密码。
排查与解决步骤
1. 检查私钥字符串格式
从.env读取的私钥字符串可能存在格式问题(比如换行符丢失或转义),导致paramiko无法正确解析:
- 在容器内临时修改
main.py,打印os.environ.get("SSH_PKEY")的内容,和宿主机上的私钥文件对比,确保换行符、开头结尾的-----BEGIN RSA PRIVATE KEY-----/-----END RSA PRIVATE KEY-----完全一致。 - 如果
.env里的私钥是手动复制的,建议用命令将私钥转为单行格式(如cat id_rsa | tr '\n' '\\n')后再写入.env,避免格式错误。
2. 修复Dockerfile的虚拟环境无效问题
Dockerfile中RUN . venv/bin/activate是无效的——每个RUN命令独立运行shell,虚拟环境不会延续到后续步骤,导致依赖安装在系统Python而非虚拟环境,可能引发版本不一致。修正后的Dockerfile:
FROM python:3.11.7-slim WORKDIR /app # 合并apt命令减少镜像层数,清理缓存 RUN apt update && apt install -y openssh-client && rm -rf /var/lib/apt/lists/* RUN python3 -m venv venv COPY ./requirements.txt ./ # 确保在虚拟环境中安装依赖 RUN . venv/bin/activate && pip install --no-cache-dir -r requirements.txt COPY ./main.py ./ COPY ./.env ./ # 使用虚拟环境的Python执行程序 CMD ["/app/venv/bin/python", "main.py"]
3. 处理主机密钥验证问题
容器内首次连接目标SSH服务器时,若未将主机指纹加入known_hosts,可能导致认证被拒:
- 测试环境临时方案:修改
main.py中的SSHTunnelForwarder配置,关闭主机密钥检查:tunnel = sshtunnel.SSHTunnelForwarder( (os.environ.get("SSH_HOST"), 22), ssh_username=os.environ.get("SSH_USER"), ssh_pkey=paramiko.RSAKey.from_private_key( io.StringIO(os.environ.get("SSH_PKEY")), ), remote_bind_addresses=[("0.0.0.0", 5432)], logger=logger, ssh_options={"StrictHostKeyChecking": "no"}, ) - 生产环境规范方案:在Dockerfile中预先添加目标主机的指纹(构建时需传入SSH_HOST变量):
ARG SSH_HOST RUN ssh-keyscan ${SSH_HOST} >> /root/.ssh/known_hosts
4. 验证依赖版本一致性
确保容器内的依赖版本与宿主机完全一致:
- 宿主机执行:
pip list | grep -E "sshtunnel|paramiko|python-dotenv" - 容器内执行:
pip list | grep -E "sshtunnel|paramiko|python-dotenv"
若版本不一致,重新构建容器时加上--no-cache参数避免缓存旧依赖:
docker build --no-cache -t test .
内容的提问来源于stack exchange,提问作者Kilian Calefice
相关产品推荐
相关产品推荐

