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番目のノードに参加します。
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にはnotはreplicatedのように見えます。
私は通常、これらのコマンドを入力するために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モードで機能しないことです。
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を実行するだけです。
編集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
を実行すると、役立つエラーメッセージが表示される場合があります。
サービス名だけでswarm container hash全体を渡す必要なく、コンテナ名をフィルタリングすることでコマンドを実行できます。このような:
docker exec $(docker ps -q -f name=servicename) ls
Docker APIの使用
現時点では、Dockerはdocker service exec
やdocker 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 と呼ばれる別のプロジェクトもあります。これは、多かれ少なかれssh
とdocker exec
のラッパーのようです。
参照:
Swarmノードにジャンプして、実行中のdockerコンテナを一覧表示できます:
docker container ls
これにより、コンテナ名が次のような形式で表示されます。containername.1.q5k89uctyx27zmntkcfooh68f
その後、通常のexecオプションを使用して、その上でコマンドを実行できます。
docker container exec -it containername.1.q5k89uctyx27zmntkcfooh68f bash
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接続を受け入れる必要があります
サービス名で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