#Docker: Execute arbitrary docker commands on any container in the swarm from a manager node

By | March 21, 2017

How to execute an arbitrary command on any docker container running in a docker swarm ?

There is no way of directly executing a ‘docker exec’ on a container in the swarm.
On a swarm we can define stack of services and directly only services are visible. The containers that run the actual service and their location is hidden to us.

STEP 1: Find the task associated to a service

To find out the tasks associated with a service execute on a swarm manager node:


# docker service ps -q ${SERVICE_NAME} | head -n $index

Where:
– SERVICE_NAME = a variable containing the fully qualified name of a service stackname+servicename
– index = a variable indicating the index of a service replica. In case the service has several replicas the “docker service ps” command returns the list of task IDs of the replicas.
The -q parameter ensure that we will return just the list of tasks IDs.
Note that a service can have several tasks associated, but each task has only one container associated. With the above I return only the one task from the list.

STEP 2: Find the container ID associated to a task

With the following command inspect a task from the swarm with a given filter:


# docker inspect -f "{{.Status.ContainerStatus.ContainerID}}" ${TASK_ID}

Where TASK_ID = a variable containing the task ID found at STEP 1

STEP 3: Find the ID of the swarm node where the task is running

With the following command inspect the task with a given filter:


# docker inspect -f "{{.NodeID}}" ${TASK_ID}

Where TASK_ID = a variable containing the task ID found at STEP 1

STEP 4: Find the IP of the swarm node where the task is running

With the following command inspect the node with a given filter:


# docker inspect -f {{.Status.Addr}} ${NODE_ID}

Where NODE_ID = a variable containing the node ID found at STEP 3

STEP 5: Execute with ssh a remote docker exec
We assume that ssh is setup between the manager node and all the other nodes of the swarm as a passwordless login, using certificates.
On the swarm manager node execute the following to generate the ssh key pair.


# ssh-keygen

Then using ssh-cpy-id copy the public key of the swarm manager to all the other nodes


# ssh-copy-id -i .ssh/id_rsa_pub worker1

The following command will execute the remote docker exec command in a bash heredoc block:


ssh -T ${NODE_IP} << EOSSH    docker exec ${CONT_ID} bash -c "echo 'host.name=${SERVICE_NAME}' >> /var/lib/jetty/resources/server.properties"
EOSSH

STEP 6: Put everything in one script.
The simple case is when a service has only one replica. In this case we have only one task associated with a service.


cat docker-exec.sh

#!/bin/bash
SERVICE_NAME=$1
COMMAND=$2
TASK_ID="$(docker service ps -q ${SERVICE_NAME})"
CONT_ID="$(docker inspect -f "{{.Status.ContainerStatus.ContainerID}}" ${TASK_ID})"	
NODE_ID="$(docker inspect -f "{{.NodeID}}" ${TASK_ID})"
NODE_IP="$(docker inspect -f {{.Status.Addr}} ${NODE_ID})"
ssh -T ${NODE_IP} << EOSSH
   docker exec ${CONT_ID} bash -c "${COMMAND}"
EOSSH

To use the new script do the following:


docker-exec.sh stack_db "echo 'host.name=${SERVICE_NAME}' >> /var/lib/jetty/resources/server.properties" 

The same can be done for “docker cp” with the note that data that is copied to/from the container will reside on the local node where the container runs.

Contribute to this site maintenance !

This is a self hosted site, on own hardware and Internet connection. The old, down to earth way 🙂. If you think that you found something useful here please contribute. Choose the form below (default 1 EUR) or donate using Bitcoin (default 0.0001 BTC) using the QR code. Thank you !

€1.00

Advertisements

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.