web-dev-qa-db-ja.com

docker swarmサービス内でコマンドを実行します

  1. Swarmモードを初期化します。

    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. 2番目のノードに参加します。

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

このswarmにマネージャーを追加するには、「docker swarm join-token manager」を実行し、指示に従います。

# 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

上記のように、redisにはレプリカがありますが、minicondaにはnotreplicatedのように見えます。

私は通常、これらのコマンドを入力するためにminicondaコンテナーにログインします。

/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

問題は、docker exec -it XXX bashコマンドがswarmモードで機能しないことです。

31
shantanuo

Localhostのサービスの対応するインスタンスにアクセスするためのライナーが1つあります。

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

PowerShellでテストされていますが、bashは同じでなければなりません。 onelinerは最初のインスタンスにアクセスしますが、「1」を2か所でアクセスするインスタンスの番号に置き換えて、他のインスタンスを取得します。

より複雑な例は、分散型の場合です。

#! /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

このスクリプトは、後で次のように使用できます。

swarm_bash stack_task 1

必要なノードでbashを実行するだけです。

29
user1936595

編集2017-10-06:

現在、--attachableフラグを使用してオーバーレイネットワークを作成し、コンテナがネットワークに参加できるようにすることができます。これは多くの柔軟性を可能にするため、素晴らしい機能です。

例えば。

$ 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>
....

Docker Swarm Modeサービスでdocker execを実行することはできません。ただし、コンテナを実行しているノードを確認してから、コンテナで直接execを実行できます。例えば。

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

あなたの場合、まずサービスがminicondaコンテナを起動できない理由を見つける必要があります。 docker service ps miniconda3を実行すると、役立つエラーメッセージが表示される場合があります。

19
ronkot

サービス名だけでswarm container hash全体を渡す必要なく、コンテナ名をフィルタリングすることでコマンドを実行できます。このような:

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

10
isca

Docker APIの使用

現時点では、Dockerはdocker service execdocker stack execなどのAPIを提供していません。ただし、これに関しては、この機能を扱う2つの問題が既に存在します。

(最初の問題に関して、私にとっては、この問題がまさにこの種の機能を扱っていることは直接明確ではありませんでした。しかし Exec for Swarm は閉じられ、 Dockerサービスの複製としてマークされましたexec issue。)

HTTPを介したDockerデーモンの使用

BMitch on swarm managerからdocker execを実行 で述べたように、HTTPを使用するようにDockerデーモンを設定し、sshを使用せずにすべてのノードに接続することもできます。ただし、Dockerに既に統合されている TLS認証 を使用してこれを保護する必要があります。その後、次のようにdocker execを実行できます。

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

skopos-plugin-swarm-execの使用

問題を解決し、Dockerデーモンをバインドする必要な機能を提供すると主張するgithubプロジェクトが存在します。

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

私が見る限り、これは、docker execが実行されるべき場所にあるコンテナが存在する同じノードに別のコンテナを作成することで機能します。このノードでこのコンテナは、docker execをローカルで実行できるようにdockerデーモンソケットをマウントします。
詳細については、次を参照してください。 skopos-plugin-swarm-exec

ドッカースウォームヘルパーの使用

docker swarm helpers と呼ばれる別のプロジェクトもあります。これは、多かれ少なかれsshdocker execのラッパーのようです。

参照:

9
Murmel

Swarmノードにジャンプして、実行中のdockerコンテナを一覧表示できます:

docker container ls

これにより、コンテナ名が次のような形式で表示されます。containername.1.q5k89uctyx27zmntkcfooh68f

その後、通常のexecオプションを使用して、その上でコマンドを実行できます。

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

docker swarm cluster用の小さなスクリプトを作成しました。このスクリプトは3つのパラメーターを取ります。 1つ目は接続するサービス、2つ目は実行するタスク、/bin/bashまたは実行する他のプロセスです。 3番目はオプションで、bashまたはshの-cオプションを埋めます

-nは、ノードへの接続を強制するオプションです

サービスを実行し、コマンドを実行するノードを取得します。

#! /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"

:これには、Dockerノードがワーカーノードのポート2375でdockerを公開することでtcp接続を受け入れる必要があります

4

サービス名でdocker swarmのexecコマンドにスクリプトを書きました。たとえば、cronで使用できます。また、bashパイプラインを使用して、すべてのパラメーターをdocker execコマンドに渡すこともできます。ただし、サービスが開始された同じノードでのみ機能します。私はそれが誰かを助けることができればいいのに

#!/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;

使用例:

./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