繁体   English   中英

docker容器内调用命令

[英]Call commands within docker container

我有一个 docker 容器,我需要在其中运行一些命令。 通常,我通过运行以下命令手动执行此操作:

host> docker exec -it my-container bash
container> eval $(ssh-agent)
container> ssh-add ~/.ssh/my-key
<TYPE PASSPHRASE!!!>
container> pytest

我试图从子流程调用docker exec -it ,但我无法模仿与手动工作流相同的行为。 我无法一一发送命令,因为 ssh 密钥仅针对当前 session 加载,如果我以非交互方式运行它,我将无法使用该密钥。

我有两个问题 - 我需要通过 stdin 输入密码(我没有看到将它与ssh-add一起提供的方法),我想知道pytest何时退出和返回代码。

实现这一目标的最无缝方式是什么? 我宁愿避免安装额外的依赖项,但如果有必要,我可以使用一些东西。

ssh-agent 监听 Unix 套接字; 它的位置在$SSH_AUTH_SOCK环境变量中。 您可以使用 Docker 绑定安装( docker run -v选项)将此套接字注入容器。 然后,当您在主机上运行ssh-add时,只要套接字可访问并且主机上的环境变量设置正确,容器就可以访问代理中的凭据。

我不会在这里使用docker exec 一个容器通常运行一些单一的命令; 假设您的容器正在运行 Flask 或 Django 应用程序。 当 Django 应用程序正在运行时,您通常不会“进入”该应用程序以在服务器内部运行其单元测试。 一个单独的容器和一个单独的进程更有意义。

我在这里可能使用的调用看起来更像:

eval $(ssh-agent)                           # if not already done on login
ssh-add                                     # if not already done on login
docker run \
  --rm \                                    # delete temporary test container when done
  -v "$SSH_AUTH_SOCK:/tmp/ssh-auth.sock" \  # mount ssh socket into container
  -e SSH_AUTH_SOCK=/tmp/ssh-auth.sock \     # set socket location to mounted socket
  -u $(id -u) \                             # run as host user (with permissions on the socket)
  your-image \
  pytest                                    # override command to run in container

我会惊讶地看到单元测试实际上取决于对特定 ssh 凭据的访问; 您还可能会发现,在构建 Docker 映像之前,重组测试以模拟需要这些凭据的服务客户端或在主机上的 Python 虚拟环境中运行这些测试会更容易。

我发现 expect(或者在 python 的情况下,pexpect)在您不得不提供用户输入的情况下非常有用。 这是一个执行示例的简单脚本(诚然,还有其他依赖项):

#!/usr/bin/env python
import pexpect
from getpass import getpass

prompt = ">"
child = pexpect.spawn ('docker exec -it my-container bash'))  
child.expect (prompt)
child.sendline ('eval $(ssh-agent)')
child.expect (prompt)
child.sendline ('ssh-add ~/.ssh/my-key')
child.expect ('Enter passphrase for /root/.ssh/my-key:')
password = getpass( prompt="Private Key Password:")
child.sendline (password)
child.expect (prompt)
child.sendline ("pytest")

我从https://pexpect.readthedocs.io/en/stable/overview.html中获取示例并输入您的命令。

关于提示的注释。 当我测试上面的代码时,我容器中的 bash shell 有一个 '$' 提示符。 我认为我很幸运“$”对我有用,因为它基本上是一个有效的正则表达式。 您的里程数可能因“>”提示而异,但您可能还需要注意上述同一页面上有关 CR/LF 的信息。

我假设当您启动容器时,您安装了 ~/.ssh 目录。 当我启动我的容器来验证上面的代码时,我添加了挂载选项: -v ~/.ssh:/root/.ssh

您必须改为运行此命令以避免输入密码

sshpass -p [PASSWORD] ssh [USER]@172.17.0.2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM