python - 使用 Vagrant 和 Docker 运行 Python SSH 单元测试

标签 python docker vagrant fabric

如何配置 Vagrant 以使用 Docker 作为其提供者并使用 Fabric 连接到它?我正在尝试运行一些单元测试,以根据 Ubuntu 18.04 的原始未修改镜像验证服务器配置工具。我不是在构建自定义图像。

我的 Vagrantfile 是:

Vagrant.configure("2") do |config|
  config.vm.provider "docker" do |d|
    d.image = "ubuntu:18.04"
    d.remains_running = true
  end
end

我的 Python unittest tests.py 文件如下所示:

import unittest

import vagrant

from fabric.api import settings, run

class Tests(unittest.TestCase):

    def test_connect_to_server(self):

        v = vagrant.Vagrant('.', quiet_stdout=False, quiet_stderr=False)
        v.up(provider='docker')
        with settings(host_string=v.user_hostname_port(), key_filename=v.keyfile(), disable_known_hosts=True):

            run('echo "hello"')

Vagrant 似乎能够创建 Docker 实例,但在 Fabric 连接之前很快就失败了,并出现错误:

Bringing up machine with provider docker...
Bringing machine 'default' up with 'docker' provider...
==> default: Creating the container...
    default:   Name: ubuntu18_docker_default_1568669393
    default:  Image: ubuntu:18.04
    default: Volume: /path/to/my/project:/vagrant
    default:  
    default: Container created: c5fb82fa523f0774
==> default: Starting container...
==> default: Waiting for container to enter "running" state...
The container started either never left the "stopped" state or
very quickly reverted to the "stopped" state. This is usually
because the container didn't execute a command that kept it running,
and usually indicates a misconfiguration.

If you meant for this container to not remain running, please
set the Docker provider configuration "remains_running" to "false":

  config.vm.provider "docker" do |d|
    d.remains_running = false
  end

因此,默认镜像似乎正在运行,但它不会保持运行状态。如何配置 Docker 以保持镜像运行而不立即退出,以便我可以使用 Fabric 对其测试 SSH 命令?

编辑:按照 LinPy 的建议,将我的 Vagrantfile 修改为:

我的 Vagrantfile 是:

Vagrant.configure("2") do |config|
  config.vm.provider "docker" do |d|
    d.image = "ubuntu:18.04"
    d.remains_running = true
    d.cmd = ["tail", "-f", "/dev/null"]
  end
end

修复了初始错误,但仍然导致测试因新错误而失败:

Bringing up machine with provider docker...
Bringing machine 'default' up with 'docker' provider...
==> default: Creating the container...
    default:   Name: ubuntu18_docker_default_1568754416
    default:  Image: ubuntu:18.04
    default:    Cmd: tail -f /dev/null
    default: Volume: /path/to/my/project:/vagrant
    default:  
    default: Container created: 0e5023317321c5cf
==> default: Starting container...
==> default: Provisioners will not be run since container doesn't support SSH.
v.user_hostname_port(): vagrant@172.17.0.2:22
v.keyfile(): /home/myuser/.vagrant.d/insecure_private_key
[vagrant@172.17.0.2:22] run: echo "hello"
Keeping VM.
E
======================================================================
ERROR: test_dev_setup_ubuntu18 (__main__.Tests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/path/to/my/project/.env/lib/python3.7/site-packages/fabric/network.py", line 478, in connect
    client.connect(**kwargs)
  File "/path/to/my/project/.env/lib/python3.7/site-packages/paramiko/client.py", line 368, in connect
    raise NoValidConnectionsError(errors)
paramiko.ssh_exception.NoValidConnectionsError: [Errno None] Unable to connect to port 22 on 172.17.0.2

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "tests.py", line 167, in test_dev_setup_ubuntu18
    run('echo "hello"')
  File "/path/to/my/project/.env/lib/python3.7/site-packages/fabric/network.py", line 692, in host_prompting_wrapper
    return func(*args, **kwargs)
  File "/path/to/my/project/.env/lib/python3.7/site-packages/fabric/operations.py", line 1095, in run
    shell_escape=shell_escape, capture_buffer_size=capture_buffer_size,
  File "/path/to/my/project/.env/lib/python3.7/site-packages/fabric/operations.py", line 935, in _run_command
    channel=default_channel(), command=wrapped_command, pty=pty,
  File "/path/to/my/project/.env/lib/python3.7/site-packages/fabric/state.py", line 435, in default_channel
    chan = _open_session()
  File "/path/to/my/project/.env/lib/python3.7/site-packages/fabric/state.py", line 416, in _open_session
    transport = connections[env.host_string].get_transport()
  File "/path/to/my/project/.env/lib/python3.7/site-packages/fabric/network.py", line 156, in __getitem__
    self.connect(key)
  File "/path/to/my/project/.env/lib/python3.7/site-packages/fabric/network.py", line 148, in connect
    user, host, port, cache=self, seek_gateway=seek_gateway)
  File "/path/to/my/project/.env/lib/python3.7/site-packages/fabric/network.py", line 610, in connect
    raise NetworkError(msg, e)
fabric.exceptions.NetworkError: Low level socket error connecting to host 172.17.0.2 on port 22: Unable to connect to port 22 on 172.17.0.2 (tried 1 time)

我认为关键消息是“由于容器不支持 SSH,Provisioners 将不会运行。”,但我不明白这一点,因为 Ubuntu 18.04 应该预装 SSHD。我尝试修改 cmd 来安装 SSH,其变化如下:

d.cmd = ["apt", "-yq", "install", "openssh-server", "&&", "/etc/init.d/ssh", "start", "&&", "/bin/bash"]

但这没有任何效果,并且仍然返回相同的错误。为什么 Docker 报告 Ubuntu 容器不支持 SSH?

最佳答案

试试这个:

Vagrant.configure("2") do |config|
  config.vm.provider "docker" do |d|
    d.run "test",
       d.image : "ubuntu:18.04",
       cmd: "tail -f /dev/null",

  end
end

参见this

更新

使用以下命令来使用SSH:

Dockerfile:

FROM ubuntu

RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:THEPASSWORDYOUCREATED' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

Vagrant 文件:

Vagrant.configure("2") do |config|
  config.vm.provision "docker" do |d|
     d.build_image "/vagrant/app",
        args: "-t myimage"
  end
end

  Vagrant.configure("2") do |config|
      config.vm.provision "docker" do |d|
       d.run "test",
         d.image : "myimage",
         args: "-p 3333:22"
      end
    end

PS:确保您的 Dockerfile 位于 /vagrant/app 并且您的 python 脚本应连接到端口 3333

关于python - 使用 Vagrant 和 Docker 运行 Python SSH 单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57964827/

相关文章:

docker - Drupal 与 Docker 的数据库连接错误 - SQLSTATE[HY000] [2002]

vagrant - 在 Vagrant 中使用 Atom 编辑器

ruby - Play2 Chef Recipe 未安装在 Vagrant 机器上

python - Django Haystack SOLR 中的排序顺序

python - 通过 shell 脚本运行时为 "scrapy: command not found"

python - 为什么我的代码会打印 "built-in method"和一些十六进制数字?

azure - 如何使用 azure 管道变量为我的 docker 镜像设置环境变量?

macos - Docker 无法在 Mac OS 上挂载/var 下的任何文件夹

git - 克隆 git 时 vagrant setup 抛出 Permission denied (publickey)

python - 如何通过shell激活PyCharm创建的venv?