0
votes

Utiliser Vagrant et Docker pour exécuter des unittests Python SSH

Comment configurer Vagrant pour utiliser Docker comme fournisseur et s'y connecter avec Fabric? J'essaie d'exécuter des tests unitaires pour valider un outil de provisioning de serveur par rapport à une image brute non modifiée d'Ubuntu 18.04. Je ne construis pas d'image personnalisée.

Mon Vagrantfile est:

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

Mon fichier Python unittest tests.py ressemble à:

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)

Vagrant semble capable de créer l'instance Docker, mais il échoue rapidement avant que Fabric puisse se connecter, avec l'erreur:

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

Il semble donc que l'image par défaut est en cours d'exécution, mais elle ne reste pas en cours d'exécution. Comment configurer Docker pour maintenir l'image en cours d'exécution et ne pas quitter immédiatement, afin de pouvoir tester les commandes SSH avec Fabric?

Edit: Suite à la suggestion de LinPy, en modifiant mon Vagrantfile en:

Mon Vagrantfile est:

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

corrige l'erreur initiale, mais entraîne toujours l'échec du test avec la nouvelle erreur:

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"')

Je suppose que le message clé est «Les fournisseurs ne seront pas exécutés car le conteneur ne prend pas en charge SSH.», Mais je ne comprends pas cela car Ubuntu 18.04 devrait être livré avec SSHD préinstallé. J'ai essayé de modifier la cmd pour installer SSH, avec des variations de:

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

mais cela n'a eu aucun effet et renvoie toujours la même erreur. Pourquoi Docker signale-t-il que le conteneur Ubuntu ne prend pas en charge SSH?


0 commentaires

3 Réponses :


0
votes

essaye ça:

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

voir ça

mise à jour

utilisez ce qui suit pour utiliser 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"]

Vagrantfile:

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

PS: assurez-vous que votre Dockerfile est dans /vagrant/app et que votre script python doit se connecter au port 3333


2 commentaires

Cela semble aller dans la bonne direction. Mais maintenant, j'obtiens juste l'erreur: [Errno None] Unable to connect to port 22 on 172.17.0.2 .


Oui, car l'image que vous utilisez n'a pas installé ssh. Vous devez installer et configurer ssh



0
votes

rencontré le même problème récemment:
pour l'exemple suivant, j'ai donné "nginx_demo" comme nom de conteneur.

  1. nous utilisons Docker en tant que fournisseur , pas VM en tant que fournisseur.
    donc nous ne pouvons pas ssh dans le conteneur.

  2. il y a des hacks pour exécuter des commandes dans le conteneur

    $ vagrant docker-logs nginx_demo -f  
    

    par exemple : ici j'utilise l'image nginx , maintenant récupérons la version nginx

    $ vagrant docker-exec -it nginx_demo -- bash 
    

    ici nginx_demo est le nom qui sera donné dans le Vagrantfile . (le nom peut être n'importe quoi)

    $ vagrant list-commands  
    
  3. pour connaître les autres commandes docker prises en charge sous vagrant:

    d.name = "nginx_demo"  
    
  4. pour attacher à un conteneur déjà en cours d'exécution

    $ vagrant docker-run nginx_demo -- nginx -v  
    
  5. pour récupérer les logs du conteneur docker

    $ vagrant docker-run <name> -- <commands>  
    

pour en savoir plus avec un exemple approprié
https://medium.com/@elliot004/vagrant-docker-provider-windows-3350758fc8b3


0 commentaires

0
votes

Au cas où quelqu'un aurait ce problème, j'ai créé un vagrant-docker-communicator:

https://github.com/ProxiBlue/vagrant-communicator-docker

Cela ne vous permet pas d'exécuter `` vagrant ssh '', de SSH à la boîte, car beaucoup d'images de docker ne disposent pas réellement de SSH en tant que service. Vous pouvez utiliser la méthode prescrite indiquée dans d'autres réponses pour utiliser docker pour vous connecter à une instance en cours d'exécution via l'invite bash.

Le plugin permet le provisionnement sur une image docker sans ssh


0 commentaires