web-dev-qa-db-fra.com

exécuter une commande dans le service Sword Docker

  1. Initialiser le mode essaim:

    root@ip-172-31-44-207:/home/ubuntu# docker swarm init --advertise-addr 172.31.44.207
    
    Swarm initialized: current node (4mj61oxcc8ulbwd7zedxnz6ce) is now a manager.
    
    To add a worker to this swarm, run the following command:
    
  2. Rejoignez le deuxième noeud:

    docker swarm join \
    --token SWMTKN-1-4xvddif3wf8tpzcg23tem3zlncth8460srbm7qtyx5qk3ton55-6g05kuek1jhs170d8fub83vs5 \
    172.31.44.207:2377
    

Pour ajouter un gestionnaire à cet essaim, exécutez "Gestionnaire des jetons de jointure de Docker Swarm" et suivez les instructions.

# start 2 services
docker service create continuumio/miniconda3 

docker service create --name redis redis:3.0.6


root@ip-172-31-44-207:/home/ubuntu# docker service ls
ID            NAME        REPLICAS  IMAGE                   COMMAND
2yc1xjmita67  miniconda3  0/1       continuumio/miniconda3
c3ptcf2q9zv2  redis       1/1       redis:3.0.6

Comme indiqué ci-dessus, redis a sa réplique tandis que miniconda fait pas semble être répliqué.

Je me connecte habituellement au conteneur miniconda pour taper ces commandes:

/opt/conda/bin/conda install jupyter -y --quiet && mkdir /opt/notebooks && /opt/conda/bin/jupyter notebook --notebook-dir=/opt/notebooks --ip='*' --port=8888 --no-browser

Le problème est que docker exec -it XXX bash La commande ne fonctionne pas avec le mode Essaim.

31
shantanuo

Il existe une seule ligne pour accéder à l'instance correspondante du service pour localhost:

docker exec -ti stack_myservice.1.$(docker service ps -f 'name=stack_myservice.1' stack_myservice -q --no-trunc | head -n1) /bin/bash

Il est testé sur PowerShell, mais bash devrait être identique. L'un des doublons accède à la première instance, mais remplace "1" par le numéro de l'instance à laquelle vous souhaitez accéder à deux endroits pour en obtenir une autre.

Un exemple plus complexe concerne le cas distribué:

#! /bin/bash

set -e

exec_task=$1
exec_instance=$2

strindex() { 
  x="${1%%$2*}"
  [[ "$x" = "$1" ]] && echo -1 || echo "${#x}"
}

parse_node() {
  read title
  id_start=0
  name_start=`strindex "$title" NAME`
  image_start=`strindex "$title" IMAGE`
  node_start=`strindex "$title" NODE`
  dstate_start=`strindex "$title" DESIRED`
  id_length=name_start
  name_length=`expr $image_start - $name_start`
  node_length=`expr $dstate_start - $node_start`

  read line
  id=${line:$id_start:$id_length}
  name=${line:$name_start:$name_length}
  name=$(echo $name)
  node=${line:$node_start:$node_length}
  echo $name.$id
  echo $node
}

if true; then 
   read fn 
   docker_fullname=$fn
   read nn
   docker_node=$nn 
fi < <( docker service ps -f name=$exec_task.$exec_instance --no-trunc -f desired-state=running $exec_task | parse_node )

echo "Executing in $docker_node $docker_fullname" 

eval `docker-machine env $docker_node`

docker exec -ti $docker_fullname /bin/bash

Ce script pourrait être utilisé plus tard comme:

swarm_bash stack_task 1

Il suffit d'exécuter bash sur le noeud requis.

29
user1936595

EDIT 2017-10-06:

De nos jours, vous pouvez créer le réseau de superposition avec --attachable drapeau pour permettre à tout conteneur de rejoindre le réseau. C'est une fonctionnalité intéressante car elle permet beaucoup de flexibilité.

Par exemple.

$ docker network create --attachable --driver overlay my-network
$ docker service create --network my-network --name web --publish 80:80 nginx
$ docker run --network=my-network -ti Alpine sh
(in Alpine container) $  wget -qO- web

<!DOCTYPE html>
<html>
<head>
....

Vous avez raison, vous ne pouvez pas courir docker exec sur le service en mode Docker Swarm. Mais vous pouvez toujours savoir quel nœud exécute le conteneur, puis exécuter directement exec sur le conteneur. Par exemple.

docker service ps miniconda3  # find out, which node is running the container
eval `docker-machine env <node name here>`
docker ps  # find out the container id of miniconda
docker exec -it <container id here> sh

Dans votre cas, vous devez d’abord comprendre pourquoi le service ne peut pas obtenir le conteneur miniconda. Peut-être que courir docker service ps miniconda3 montre quelques messages d'erreur utiles ..?

19
ronkot

Vous pouvez exécuter des commandes en filtrant le nom du conteneur sans avoir besoin de transmettre l'intégralité du hachage du conteneur Swarm, uniquement par le nom du service. Comme ça:

docker exec $(docker ps -q -f name=servicename) ls

10
isca

Utilisation de l'API Docker

À l'heure actuelle, Docker ne fournit pas une API comme docker service exec ou docker stack exec pour ça. Mais à ce propos, il existe déjà deux problèmes liés à cette fonctionnalité:

(En ce qui concerne le premier problème, il n’est pas clair pour moi que ce problème concerne exactement ce type de fonctionnalité. Mais Exec for Swarm a été fermé et marqué comme une copie du service service Docker exec issue.)

Utilisation du démon Docker sur HTTP

Comme mentionné par BMitch sur exécutez docker exec depuis swarm manager , vous pouvez également configurer le démon Docker pour qu'il utilise HTTP et se connecter à chaque nœud sans avoir besoin de ssh. Mais vous devriez protéger cela en utilisant authentification TLS qui est déjà intégré à Docker. Ensuite, vous pourrez exécuter le docker exec comme ça:

docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem \
    -H=$Host:2376 exec $containerId $cmd

Utilisation de skopos-plugin-swarm-exec

Il existe un projet github qui prétend résoudre le problème et fournit la fonctionnalité souhaitée liant le démon docker:

docker run -v /var/run/docker.sock:/var/run/docker.sock \
    datagridsys/skopos-plugin-swarm-exec \
    task-exec <taskID> <command> [<arguments>...]

Autant que je sache, cela fonctionne en créant un autre conteneur sur le même nœud que celui-ci où réside le docker exec devrait être exécuté le. Sur ce nœud, ce conteneur monte le socket du docker daemon pour pouvoir exécuter docker exec _ localement.
Pour plus d'informations, consultez: skopos-plugin-swarm-exec

Utilisation des aides de Docker Swarm

Il y a aussi un autre projet appelé docker swarm helpers qui semble être plus ou moins un wrapper autour de ssh et docker exec.

Référence:

9
Murmel

Vous pouvez sauter dans un nœud Swarm et répertorier les conteneurs Docker exécutés à l'aide de:

docker container ls

Cela vous donnera le nom du conteneur dans un format similaire à: Containername.1.q5k89uctyx27zmntkcfooh68f

Vous pouvez ensuite utiliser l’option normale exec pour y exécuter des commandes:

docker container exec -it containername.1.q5k89uctyx27zmntkcfooh68f bash
5
JP Santana

créé un petit script pour notre cluster docker swarm. ce script prend 3 paramètres. le premier est le service auquel vous voulez vous connecter, puis la tâche que vous voulez exécuter peut être /bin/bash ou tout autre processus que vous souhaitez exécuter. La troisième est optionnelle et remplira l'option -c pour bash ou sh

-n est facultatif pour le forcer à se connecter à un nœud

il récupère le nœud qui exécute le service et exécute la commande.

#! /bin/bash

set -e

task=${1}
service=$2
bash=$3

serviceID=$(Sudo docker service ps -f name=$service -f desired-state=running $service -q --no-trunc |head -n1)
node=$(Sudo docker service ps -f name=$service -f desired-state=running $service --format="{{.Node}}"| head -n1 )

Sudo docker -H $node exec -it $service".1."$serviceID $bash -c "$task"

note: les nœuds du menu fixe doivent accepter les connexions TCP en exposant le menu fixe sur le port 2375 sur les nœuds de travail.

4
Brian van Rooijen

J'ai écrit le script pour exécuter la commande dans Docker swarm par nom de service. Par exemple, il peut être utilisé dans cron. Vous pouvez aussi utiliser les pipelines bash et passer tous les paramètres à docker exec commande. Mais ne fonctionne que sur le même nœud où le service a démarré. Je souhaite que cela puisse aider quelqu'un

#!/bin/bash
# swarm-exec.sh
set -e

for ((i=1;i<=$#;i++)); do
    val=${!i}
    if [ ${val:0:1} != "-" ]; then
        service_id=$(docker ps -q -f "name=$val");
        if [[ $service_id  == "" ]]; then
            echo "Container $val not found!";
            exit 1;
        fi
        docker exec ${@:1:$i-1} $service_id ${@:$i+1:$#};
        exit 0;
    fi
done
echo "Usage: $0 [OPTIONS] SERVICE_NAME COMMAND [ARG...]";
exit 1;

Exemple d'utilisation:

./swarm-exec.sh app_postgres pg_dump -Z 9 -F p -U postgres app > /backups/app.sql.gz

echo ls | ./swarm-exec.sh -i app /bin/bash

./swarm-exec.sh -it some_app /bin/bash
3
TIO