将SSH密钥注入Docker容器

问题描述

我正在尝试找到一种用于将SSH密钥注入到容器中的“全局”解决方案。我知道有几种解决方案,包括docker build kit等...但是我不想构建映像并注入SSH密钥。我想通过docker compose使用现有映像来注入SSH密钥。

我使用以下docker compose文件

version: '3.1'

services:
  server1:
    image: XXXXXXX
    container_name: server1
    command: bash -c "/root/init.sh && python3 /root/my_python.py"
    environment:
      - MANAGED_HOST=mserver
    volumes:
      - ./init.sh:/root/init.sh
    secrets:
      - id_rsa

secrets:
   id_rsa:
     file: /home/user/.ssh/id_rsa

init.sh如下:

#!/bin/bash

eval "$(ssh-agent -s)" > /dev/null
if [ ! -d "/root/.ssh/" ]; then
    mkdir /root/.ssh
    ssh-keyscan $MANAGED_HOST > /root/.ssh/kNown_hosts
fi
ssh-add -k /run/secrets/id_rsa

如果我使用参数命令运行docker compose bash -c "/root/init.sh && python3 /root/my_python.py",然后到适当的远程主机($ MANAGED_HOST)的SSH身份验证不起作用。

代理程序正在运行:

root         8     1  0 12:50 ?        00:00:00 ssh-agent -s

kNown_hosts可以:

root@c67655d87ced:~# cat /root/.ssh/kNown_hosts
BLABLABLA ssh-rsa AAAAB3BLABLABLA....

并且代理正在运行,但是未添加私钥:

root@c67655d87ced:~# ssh-add -l
Could not open a connection to your authentication agent.

现在,如果我登录到容器(docker exec -it server1 / bin / bash)并从命令行逐个运行init.sh中的命令,则对适当的远程主机($ MANAGED_HOST)进行SSH身份验证)在工作?!?

任何想法,我如何通过使用docker compose使其工作?

解决方法

足以使文件$HOME/.ssh/id_rsa以适当的权限存在;您不需要运行ssh代理。

#!/bin/sh
if ! [ -d "$HOME/.ssh" ]; then
  mkdir "$HOME/.ssh"
fi
chmod 0700 "$HOME/.ssh"
if [ -n "$MANAGED_HOST" ]; then
  ssh-keyscan "$MANAGED_HOST" >> "$HOME/.ssh/known_hosts"
fi
if [ -f /run/secrets/id_rsa ]; then
  cp /run/secrets/id_rsa "$HOME/.ssh/id_rsa"
  chmod 0400 "$HOME/.ssh/id_rsa"
fi
# exec "$@"

一个典型的模式是使用Dockerfile ENTRYPOINT来执行这样的首次设置任务。这将得到passed the CMD as arguments,并且文件末尾的带注释的exec "$@"行将作为命令运行。您可以通过以下方式在映像的Dockerfile中进行设置:

FROM XXXXXX
...
# Script must be executable on the host,and must start with a
# #!/bin/sh "shebang" line
COPY init.sh /root
# MUST use JSON-array form
ENTRYPOINT ["/root/init.sh"]
# Can use any Dockerfile syntax
CMD ["python3","/root/my_python.py"]

在您的特定示例中,您正在启动init.sh作为子流程。 ssh-agent设置会设置一些环境变量,例如$SSH_AUTH_SOCK,但是当它们作为子进程运行时,它们不会传播回宿主进程。您可以使用标准的POSIX shell .内置(bash source内置是等效的,但不是标准的)来使这些环境变量在父shell的上下文中设置:

command: sh -c ". /root/init.sh && exec python3 /root/my_python.py"

exec用您通常需要的Python脚本替换了外壳包装。这也将成为ssh-agent的父进程,如果该进程刚好退出,则可能使您感到惊讶。