web-dev-qa-db-fra.com

Comment exécuter un script shell sur un hôte à partir d'un conteneur de menu fixe?

Comment contrôler l'hôte de conteneur docker?

Par exemple, comment exécuter copié dans le script hôte bash?

42
Alex Ushakov

Cela dépend VRAIMENT de ce que vous avez besoin de ce script bash!

Par exemple, si le script bash fait juste écho à une sortie, vous pouvez simplement faire

docker run --rm -v $(pwd)/mybashscript.sh:/mybashscript.sh ubuntu bash /mybashscript.sh

Une autre possibilité est que vous souhaitiez que le script bash installe un logiciel, par exemple le script pour installer docker-compose. vous pourriez faire quelque chose comme

docker run --rm -v /usr/bin:/usr/bin --privileged -v $(pwd)/mybashscript.sh:/mybashscript.sh ubuntu bash /mybashscript.sh

Mais à ce stade, vous devez vraiment savoir intimement ce que fait le script pour autoriser les autorisations spécifiques dont il a besoin sur votre hôte à partir du conteneur. 

13
Paul Becotte

Je sais que c'est une vieille question, mais la solution idéale est peut-être de se connecter à l'hôte via SSH et d'exécuter la commande comme suit:

ssh -l ${USERNAME} ${HOSTNAME} "${SCRIPT}"

METTRE À JOUR

Comme cette réponse ne cesse de générer des votes, je souhaite ajouter une note indiquant que le compte utilisé pour invoquer le script doit être un compte sans autorisation, mais uniquement exécuter ce script en tant que Sudo (cela peut être effectué à partir du fichier sudoers ).

27
Mohammed Noureldin

Utilisé un canal nommé . Sur l'hôte hôte, créez un script pour lire et lire les commandes, puis appelez eval à cet effet. 

Demandez au conteneur de menu fixe de se lire sur le tuyau nommé.

Pour pouvoir accéder au tuyau, vous devez le monter via un volume.

Ceci est similaire au mécanisme SSH (ou à une méthode similaire basée sur un socket), mais vous limite correctement au périphérique hôte, ce qui est probablement meilleur. De plus, vous n'avez pas besoin de transmettre des informations d'authentification. 

Mon seul avertissement est d'être prudent sur la raison pour laquelle vous faites cela. C'est tout à fait quelque chose à faire si vous voulez créer une méthode d'auto-mise à niveau avec une entrée utilisateur ou autre, mais vous ne voudrez probablement pas appeler une commande pour obtenir des données de configuration, car le moyen approprié serait de passer cela en argument./volume en docker. Faites également attention au fait que vous êtes en train d’évaluer, alors pensez au modèle d’autorisation. 

Certaines des autres réponses telles que l'exécution d'un script sous un volume ne fonctionneront pas de manière générique car ils n'auront pas accès à l'ensemble des ressources système, mais cela pourrait être plus approprié en fonction de votre utilisation.

9
Bradford Medeiros

Comme le rappelle Marcus, le menu fixe est essentiellement un processus d’isolation. À partir de docker 1.8, vous pouvez copier des fichiers dans les deux sens entre l'hôte et le conteneur, voir la doc de docker cp

https://docs.docker.com/reference/commandline/cp/

Une fois qu'un fichier est copié, vous pouvez l'exécuter localement

2
user2915097

Si vous souhaitez simplement démarrer un conteneur Docker sur l'hôte à partir d'un autre conteneur Docker tel que l'OP, vous pouvez partager le serveur Docker qui s'exécute sur l'hôte avec le conteneur Docker en partageant son socket d'écoute.

Vous pouvez le faire en ajoutant les arguments de volume suivants à votre commande de démarrage

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

ou en partageant /var/run/docker.sock dans votre fichier de docker, composez le fichier comme ceci:

version: '3'

services:
   ci:
      command: ...
      image: ...
      volumes
         - /var/run/docker.sock:/var/run/docker.sock

Lorsque vous exécutez la commande docker start dans votre conteneur docker, le serveur docker exécuté sur votre hôte voit la demande et met en service le conteneur frère.

crédit: http://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/

1
Matt Bucci
docker run --detach-keys="ctrl-p" -it -v /:/mnt/rootdir --name testing busybox
# chroot /mnt/rootdir
# 
0
Zibri

J'ai une approche simple.

Étape 1: Montez /var/run/docker.sock:/var/run/docker.sock (vous pourrez donc exécuter des commandes de menu dans votre conteneur)

Étape 2: Exécutez la procédure ci-dessous dans votre conteneur. La partie clé ici est ( --Hôte réseau car cela sera exécuté à partir du contexte hôte) 

docker run -i --rm --network Host -v /opt/test.sh:/test.sh Alpine: 3.7 sh /test.sh

test.sh devrait contenir les quelques commandes (ifconfig, netstat, etc.), quoi que vous ayez besoin de ... .. Maintenant, vous pourrez obtenir la sortie du contexte de l'hôte. 

0
Bala

Écrivez un serveur python de serveur simple à l'écoute sur un port (disons 8080), liez le port -p 8080: 8080 au conteneur, envoyez une requête HTTP à localhost: 8080 pour demander au serveur python de lancer des scripts écrire du code pour créer une requête HTTP curl -d '{"foo": "bar"}' localhost: 8080

#!/usr/bin/python
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
import subprocess
import json

PORT_NUMBER = 8080

# This class will handles any incoming request from
# the browser 
class myHandler(BaseHTTPRequestHandler):
        def do_POST(self):
                content_len = int(self.headers.getheader('content-length'))
                post_body = self.rfile.read(content_len)
                self.send_response(200)
                self.end_headers()
                data = json.loads(post_body)

                // Use the post data
                cmd = "your Shell cmd"
                p = subprocess.Popen(cmd, stdout=subprocess.PIPE, Shell=True)
                p_status = p.wait()
                (output, err) = p.communicate()
                print "Command output : ", output
                print "Command exit status/return code : ", p_status

                self.wfile.write(cmd + "\n")
                return
try:
        # Create a web server and define the handler to manage the
        # incoming request
        server = HTTPServer(('', PORT_NUMBER), myHandler)
        print 'Started httpserver on port ' , PORT_NUMBER

        # Wait forever for incoming http requests
        server.serve_forever()

except KeyboardInterrupt:
        print '^C received, shutting down the web server'
        server.socket.close()
0
Frank Chang