Docker容器中使用CMD写入SSH密钥失败,如何解决?
问题原因与解决方法
核心原因
- Dockerfile的CMD指令特性:Dockerfile中只会生效最后一条CMD指令,前面的所有CMD会被直接覆盖。你写了两条CMD,实际只有最后一条写入私钥的命令会被执行;同时容器启动时默认工作目录是
/,如果/.ssh目录未提前创建,这条写入命令也会因为目录不存在而失败。 - 手动用
docker exec能成功,是因为进入容器后已经手动解决了目录问题,且两条命令是依次执行的,不存在指令覆盖的情况。
修复方案
方案1:合并命令到单条CMD,确保目录与权限
修改Dockerfile的CMD指令,将两条写入命令合并,同时提前创建.ssh目录,并设置SSH要求的严格权限(否则密钥无法正常被SSH识别):
FROM public.ecr.aws/ubuntu/ubuntu:18.04_stable CMD ["sh", "-c", "mkdir -p /root/.ssh && echo $PUBLIC_KEY >> /root/.ssh/id_rsa.pub && echo $PRIVATE_KEY >> /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa && chmod 644 /root/.ssh/id_rsa.pub"]
mkdir -p /root/.ssh:确保目标目录存在,不存在则自动创建chmod命令:SSH强制要求私钥权限为600(仅所有者可读可写),公钥为644,否则会拒绝使用该密钥
方案2:使用ENTRYPOINT配合CMD(更灵活)
如果后续需要扩展容器启动逻辑,可以用ENTRYPOINT定义固定的初始化脚本,CMD作为默认执行命令:
- 在Dockerfile同目录下创建初始化脚本
init-ssh.sh:
#!/bin/sh mkdir -p /root/.ssh echo "$PUBLIC_KEY" >> /root/.ssh/id_rsa.pub echo "$PRIVATE_KEY" >> /root/.ssh/id_rsa chmod 600 /root/.ssh/id_rsa chmod 644 /root/.ssh/id_rsa.pub # 执行容器默认命令,支持外部覆盖CMD参数 exec "$@"
- 修改Dockerfile:
FROM public.ecr.aws/ubuntu/ubuntu:18.04_stable COPY init-ssh.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/init-ssh.sh ENTRYPOINT ["init-ssh.sh"] CMD ["bash"]
容器启动时会先完成SSH密钥的初始化,再执行默认的bash命令,也支持通过docker run的参数覆盖CMD执行其他命令。
内容的提问来源于stack exchange,提问作者EzyHoo
相关产品推荐
相关产品推荐

