You need to enable JavaScript to run this app. 如何将环境变量的公私钥写入Docker的.ssh目录实现SFTP连接?
优惠活动
大模型
产品
解决方案
定价
更多

如何将环境变量的公私钥写入Docker的.ssh目录实现SFTP连接?

Docker环境下SFTP .ssh目录的配置实现

现有配置的基础问题梳理

  • 原Dockerfile存在路径拼写错误:chmod 700 /test_usr/.ssh/ 中用户目录少了字母e,实际路径应为/test_user/.ssh/
  • 原DockerfileShell续行符写法错误:最后一行命令末尾附带孤立的反斜杠,会直接触发构建失败
  • 权限规则缺失:没有按ssh协议的强制要求设置目录、密钥文件的权限,会直接导致sftp客户端拒绝使用密钥

重要提醒:绝对不能直接在Dockerfile中硬编码写入密钥内容。硬编码的密钥会永久留存到镜像的每一层历史中,哪怕后续删除密钥,也能从镜像层反向导出造成泄露,完全违背当前从Vault动态注入密钥的安全设计初衷。

基础修正版实现

因为密钥值是运行时从Vault、K8s Secret动态注入的,不属于镜像构建阶段的固定内容,因此整个流程拆成两部分:镜像阶段只做无敏感信息的基础初始化,运行时阶段再读取环境变量生成密钥文件。

第一步:修正后的基础Dockerfile

镜像构建阶段只做用户、目录的基础准备,完全不涉及密钥内容处理:

# 可根据实际业务替换为你的基础镜像
FROM 你的业务基础镜像
# 创建专用系统用户,设置登录shell和家目录
# 注:Alpine系统直接用-D参数即可,Debian/Ubuntu类镜像需替换为--disabled-password --gecos ""
RUN adduser -D -s /bin/bash -h /test_user test_user \
    && mkdir -p /test_user/.ssh \
    # 按ssh要求设置.ssh目录为700权限
    && chmod 700 /test_user/.ssh \
    # 提前把目录属主改为test_user
    && chown -R test_user:test_user /test_user/.ssh

第二步:启动时初始化密钥文件

因为密钥是运行时通过环境变量传入的,需要增加一个轻量启动脚本,在业务进程启动前把环境变量内容写入对应密钥文件、校正权限:

  1. 编写初始化脚本init-ssh.sh:
#!/bin/sh
# 将环境变量中的私钥写入id_rsa文件
echo "$PRIVATE_KEY" > /test_user/.ssh/id_rsa
# 将环境变量中的公钥/信任主机内容写入known_hosts
echo "$PUBLIC_KEY" > /test_user/.ssh/known_hosts
# 严格按sftp/ssh的权限要求设置文件权限:私钥必须为600,其他文件为644
chmod 600 /test_user/.ssh/id_rsa
chmod 644 /test_user/.ssh/known_hosts
# 统一校正属主,避免权限校验失败
chown -R test_user:test_user /test_user/.ssh
# 以test_user身份启动原有业务进程
exec su test_user -c "你的业务启动命令"
  1. 把脚本接入Dockerfile:
# 复制初始化脚本到镜像
COPY init-ssh.sh /usr/local/bin/init-ssh.sh
RUN chmod +x /usr/local/bin/init-ssh.sh
# 将脚本设置为容器启动入口
ENTRYPOINT ["/usr/local/bin/init-ssh.sh"]

第三步:对应K8s Pod配置调整

把原来硬编码的env值替换为从Vault/K8s Secret读取的配置,避免密钥明文出现在Pod定义里:

apiVersion: v1
kind: Pod
metadata:
  name: envar-demo
  labels:
    purpose: demonstrate-envars
spec:
  containers:
  - name: envar-demo-container
    image: gcr.io/google-samples/node-hello:1.0
    env:
    - name: PUBLIC_KEY
      valueFrom:
        secretKeyRef:
          name: 存储SFTP密钥的Secret资源名
          key: known_hosts_content
    - name: PRIVATE_KEY
      valueFrom:
        secretKeyRef:
          name: 存储SFTP密钥的Secret资源名
          key: id_rsa_content

更优的生产级方案

直接用K8s Secret卷挂载替代环境变量传值、脚本写文件的流程,安全性和稳定性都更高:

  • 完全省掉写文件的初始化脚本:把存储密钥的Secret直接挂载到/test_user/.ssh路径,将Secret中对应私钥的key映射为id_rsa、对应known_hosts的key映射为known_hosts,挂载完成后目录结构直接符合sftp客户端的要求
  • 权限更合规:K8s Secret挂载的内容默认存储在tmpfs内存盘,不会写入容器持久层,Pod销毁后内容直接清除,不会造成泄露
  • 减少异常点:可以直接在挂载配置中设置目录700权限、私钥文件600权限,不需要额外写脚本做权限校正,从根源上避免因为权限不对导致sftp连接失败
  • 镜像更通用:镜像本身不需要内置任何和密钥处理、用户初始化相关的自定义逻辑,只需要提供基础业务运行环境即可

内容的提问来源于stack exchange,提问作者M06H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.09 10:06:00