5

I have a deployed docker stack on AWS with swarm:

docker stack deploy --with-registry-auth -c docker-stack.yml pipeline

I want to get an interactive bash session into one of the containers defined in the docker-stack.yml, but the various docker exec -ti CONTAINER_NAME /bin/bash invocations that I have tried all fail.

What is the right method to derive a container name to be passed to:

docker exec -it CONTAINER_NAME /bin/bash

given that:

docker service ps pipeline_django

returns valid service information and:

docker stack ps pipeline

returns valid stack information.

None of the documented methods of deriving the container_name from these commands work when passed to the docker exec -it command. They all fail with:

Error response from daemon: No such container

I've tried the things listed here:

execute a command within docker swarm service

Murmel
  • 4,805
  • 41
  • 50
David Watson
  • 3,304
  • 2
  • 33
  • 51
  • 1
    Did you ever find an answer? I am surprised it is nearly impossible to locate this in any documentation - such a basic operation. – Dan Nissenbaum Jan 04 '18 at 05:41
  • You can have a look at [run docker exec from swarm manager](https://stackoverflow.com/questions/44638869/run-docker-exec-from-swarm-manager), especially [BMitch's answer](https://stackoverflow.com/a/44639230/1885518) where he suggests the usage of [exposing the docker daemon via HTTPS](https://docs.docker.com/engine/security/https/) – Murmel Feb 20 '18 at 17:15

3 Answers3

2

The other answers failed, because they no not extract the container it from the task. Swarm wraps a task object around a container:

taskid=$(docker service ps -q ${servicename} |head -1)
containerid=$(docker inspect -f '{{.Status.ContainerStatus.ContainerID}}' ${taskid})
docker exec -it ${containerid} "$*"

Of course, this will only take the first container in the list.

Pylyp Dukhov
  • 38,521
  • 10
  • 57
  • 92
rhoerbe
  • 433
  • 1
  • 4
  • 17
1

Here is an example on my local macOS.

$ docker stack ls
NAME                SERVICES
gospot_web          1

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                               PORTS
qigx492p2lbe        gospot_web_web      global              1/1                 gospot/gospot-web:0.1.20.g225306b   *:80->80/tcp, *:443->443/tcp

You can use either container id or container name to access the container.

$ docker ps
CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS                 PORTS               NAMES
b3824a85d3c8        gospot/gospot-web:0.1.20.g225306b   "nginx -g 'daemon of…"   2 hours ago         Up 2 hours (healthy)   80/tcp, 443/tcp     gospot_web_web.3cqcd1v22vaon517j7p5h1d9a.wrel676fcllssrm3151ymkse9

$ docker exec -it b3824a85d3c8 sh
/ # ls
bin    etc    lib    mnt    root   sbin   sys    usr
dev    home   media  proc   run    srv    tmp    var
/ #

$ docker exec -it 
gospot_web_web.3cqcd1v22vaon517j7p5h1d9a.wrel676fcllssrm3151ymkse9 sh
/ # ls
bin    dev    etc    home   lib    media  mnt    proc   root   run    
sbin   srv    sys    tmp    usr    var
/ #

If the target service name is unique enough, you can use the following one-liner.

$ docker exec -it $(docker ps | grep gospot_web_web | awk '{print $1}') sh
/ # ls
bin    etc    lib    mnt    root   sbin   sys    usr
dev    home   media  proc   run    srv    tmp    var
/ #

Hope this helps.

gospot
  • 33
  • 5
0

You can use below command and replace SERVICE_NAME with your service name:

docker exec -it \
    $(docker stack ps pipeline| grep SERVICE_NAME | cut -d' ' -f1) /bin/bash

this command finds the container id of your service:

docker stack ps pipeline| grep SERVICE_NAME | cut -d' ' -f1
arsalanio
  • 40
  • 6