在docker swarm服务中执行命令

sha*_*nuo 35 docker-swarm

  1. 初始化群模式:

    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:
    
    Run Code Online (Sandbox Code Playgroud)
  2. 加入第二个节点:

    docker swarm join \
    --token SWMTKN-1-4xvddif3wf8tpzcg23tem3zlncth8460srbm7qtyx5qk3ton55-6g05kuek1jhs170d8fub83vs5 \
    172.31.44.207:2377
    
    Run Code Online (Sandbox Code Playgroud)

要向此群添加管理器,请运行"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
Run Code Online (Sandbox Code Playgroud)

如上所示,redis有它的复制品,而miniconda似乎没有复制.

我通常登录到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
Run Code Online (Sandbox Code Playgroud)

问题是docker exec -it XXX bash命令不适用于swarm模式.

use*_*595 31

有一个内核用于访问localhost的相应服务实例:

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

它在PowerShell上测试,但bash应该是相同的.oneliner访问第一个实例,但将"1"替换为您要在两个位置访问的实例的编号以获取另一个实例.

更复杂的例子是分布式案例:

#! /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
Run Code Online (Sandbox Code Playgroud)

此脚本可在以后用作:

swarm_bash stack_task 1
Run Code Online (Sandbox Code Playgroud)

它只是在所需节点上执行bash.

  • 关于bash脚本```$ docker service ls ID NAME MODE REPLICAS IMAGE jiecd0kb524e bar复制3/3 jwilder/whoami:latest```当我称之为```$ ./swarm_bash bar 1执行swarmm-agentpublic- 31109991000004 bar.1.vj6lqkz4wi03hn7hr6574cipg主机不存在:"swarmm-agentpublic-31109991000004"来自守护进程的错误响应:没有这样的容器:bar.1.vj6lqkz4wi03hn7hr6574cipg```我能真正执行群集模式吗?一个班轮也不适合我 (3认同)
  • 单行代码需要 - 在-q之后的no-trunc (2认同)

ron*_*kot 19


编辑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>
....
Run Code Online (Sandbox Code Playgroud)

你是对的,你不能docker exec在docker swarm模式服务上运行.但您仍然可以找到运行容器的节点,然后直接在容器上运行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
Run Code Online (Sandbox Code Playgroud)

在你的情况下,你首先要找出,为什么服务不能得到miniconda容器.也许运行docker service ps miniconda3显示一些有用的错误消息..?


isc*_*sca 11

您可以通过过滤容器名称来执行命令,而无需仅通过服务名称就传递整个swarm容器哈希。像这样:

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

  • 这不应该是推荐的方法。该服务可能有多个副本,并且该命令只能在其中一个副本中运行(如果有的话) (2认同)

Mur*_*mel 10

使用Docker API

眼下,码头工人不提供API像docker service execdocker stack exec此.但就此而言,已存在两个处理此功能的问题:

(关于第一个问题,对我来说,并不是直接明确这个问题正是处理这种功能.但是,针对Swarm的Exec已关闭并标记为Docker服务exec问题的副本.)

通过HTTP使用Docker守护程序

如前所述通过BMitch从群管理运行泊坞窗EXEC,你也可以配置泊坞窗守护进程使用HTTP和比连接到每个节点而不需要SSH的.但是你应该使用已经集成到Docker中的TLS身份验证来保护它.之后你就可以这样执行docker exec:

docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem \
    -H=$HOST:2376 exec $containerId $cmd
Run Code Online (Sandbox Code Playgroud)

使用skopos-plugin-swarm-exec

存在一个github项目声称解决问题并提供绑定docker守护程序所需的功能:

docker run -v /var/run/docker.sock:/var/run/docker.sock \
    datagridsys/skopos-plugin-swarm-exec \
    task-exec <taskID> <command> [<arguments>...]
Run Code Online (Sandbox Code Playgroud)

据我所知,这是通过在同一节点创建另一个容器来实现的,其中容器位于docker exec应该执行的位置.在此节点上,此容器安装docker守护程序套接字以便能够docker exec在本地执行.
有关更多信息,请查看:skopos-plugin-swarm-exec

使用docker swarm helpers

还有一个名为另一个项目搬运工群佣工这似乎是更多或更少的包装sshdocker exec.

参考:


Sma*_*00d 8

对于那些拥有多个副本并且只想在其中任何一个副本中运行命令的人,这里有另一个快捷方式:

docker exec -it $(docker ps -q -f name=SERVICE_NAME | head -1) bash
Run Code Online (Sandbox Code Playgroud)


Bri*_*jen 6

为我们的 docker swarm 集群创建了一个小脚本。这个脚本需要 3 个参数。首先是您要连接的服务,其次是您要运行的任务或您要运行的/bin/bash任何其他进程。第三个是可选的,将为 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"
Run Code Online (Sandbox Code Playgroud)

注意:这要求 docker 节点通过在工作节​​点上的端口 2375 上公开 docker 来接受 tcp 连接


小智 5

您可以跳入Swarm节点并使用以下命令列出正在运行的docker容器:

docker container ls
Run Code Online (Sandbox Code Playgroud)

这将为您提供类似于以下格式的容器名称:containername.1.q5k89uctyx27zmntkcfooh68f

然后,您可以使用常规exec选项在其上运行命令:

docker container exec -it containername.1.q5k89uctyx27zmntkcfooh68f bash
Run Code Online (Sandbox Code Playgroud)

  • 需要明确的是,这只会允许访问在该特定节点中运行的服务。 (2认同)