Created
October 29, 2023 02:14
-
-
Save haxwithaxe/f5473c054ef75f835ac03bafe3b8cb8e to your computer and use it in GitHub Desktop.
Run commands on docker swarm services regardless of which node it's on.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Run docker exec on service tasks on any host in a docker swarm. | |
# | |
# The first argument must be the service name all subsequent arguments are | |
# passed to that service task. | |
# | |
# The script looks for a docker context named ``node.<node hostname>``. If it | |
# doesn't exist the script will create a context by that name set to connect | |
# over ssh with the current local user as the username and the node name as the | |
# host. If the hostname belongs to the local node the ``default`` profile is | |
# copied to the required name. | |
# | |
# To override the automatically created docker context replace the context with | |
# an appropriately configured one with the same name. | |
# | |
# Author: haxwithaxe | |
# Copyright: haxwithaxe 2023 | |
# License: GPLv3 | |
set -e | |
SSH_PORT=${SSH_PORT:-22} | |
REMOTE_USER=${REMOTE_USER:-$(whoami)} | |
ensure_context() { | |
local node_host=$1 | |
local user=${2:-$REMOTE_USER} | |
local ssh_port=${3:-$SSH_PORT} | |
if ! (docker context ls --format '{{ .Name }}' | grep -q node.$node_host); then | |
if [[ "$(hostname --short)" == "$node_host" ]] || [[ "$(hostname --fqdn)" == "$node_host" ]]; then | |
docker context create --from default node.$node_host | |
else | |
docker context create node.$node_host --docker "host=ssh://${user}@${node_host}:${ssh_port}" | |
fi | |
fi | |
} | |
main() { | |
local service_name=$1 | |
shift | |
docker context use default >/dev/null 2>&1 | |
local task_id=$(docker service ps --filter 'desired-state=running' $service_name -q) | |
local node_id=$(docker inspect --format '{{ .NodeID }}' $task_id) | |
local container_id=$(docker inspect --format '{{ .Status.ContainerStatus.ContainerID }}' $task_id) | |
local node_host=$(docker node inspect --format '{{ .Description.Hostname }}' $node_id) | |
ensure_context $node_host >/dev/null 2>&1 | |
docker context use node.$node_host >/dev/null | |
local return_code=0 | |
docker exec -it $container_id "$@" || return_code=$? | |
docker context use default >/dev/null 2>&1 | |
exit $return_code | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment