Ssing ansible, I want to stop all running Docker containers except for the container whose name I will specify.
I have tried to get the container info
- name: Get info on docker host and list images
docker_host_info:
containers: yes
register: docker_info
- name: Stop running docker containers
docker_container:
name: '{{ item.Names.0}}'
state: stopped
loop: '{{ docker_info.containers }}'
when: ??
I'm not sure how to write the when
condition correctly.
Below is a reduced version of the content of the registered docker_host_info
variable
{
"changed": false,
"containers": [
{
"Command": "/bin/sh -c 'java -jar test.jar'",
"Created": 1716300998,
"Id": "abcd",
"Image": "test",
"Names": [
"/testapp"
],
"Status": "Up 12 hours"
},
{
"Command": "/bin/sh -c 'java -jar test2.jar'",
"Created": 1716300992,
"Id": "abscsd",
"Image": "test2",
"Names": [
"/testapp2"
],
"Status": "Up 12 hours"
}
]
}
I am trying to access the Names
but I am not sure how to properly use it, plus it has a /
in front of the name and I am not sure why?
I am trying to access the
Names
but I am not sure how to properly use it
The same way you used it in your docker_container
task, with item.Names.0
.
The only thing you have to remember is that when
will be templated by Ansible already, so you do not have to include it in an expression block {{ ... }}
.
The
when
clause is a raw Jinja2 expression without double curly braces
Reference: Basic conditionals with when
it has a
/
in front of the name and I am not sure why
That is correct and it will always be the case, the information gathered by the module docker_host_info
are similar to what you will get doing a docker inspect <my-container>
— because it uses the same API endpoint reference at the end of this answer.
If you do that on a container, you will realise that the internal implementation of Docker prefixes the name with a slash.
Running those two commands:
docker run \
--detach \
--rm \
--name demo \
alpine \
tail -f /dev/null
docker inspect \
demo \
-f "{{.Name}}"
Would yield:
/demo
This is also pointed out in Docker's issue tracker:
Inspect exposes the inner details of how docker is handling the container. Names are prefixed with their parent and
/
== the docker daemon. That is why every name will have this prefixed. This will be more important when nesting and multihost come into play. The / is correct for the inspect command
Reference: https://github.com/moby/moby/issues/6705
Which means that, if you want to stop the above container based on the return of the docker_host_info
module, you will have to compare its returned name to /demo
.
So, given your actual output, if you want to stop all but the first container you have running, your condition ends up being:
when: "item.Names.0 != '/testapp'"
The module docker_host_info
uses the endpoint /containers/json
:
items = self.client.get_json("/containers/json", params=params)
And if we browse the API documentation of Docker, we can see that this endpoint:
Returns a list of containers. For details on the format, see the inspect endpoint.
Reference: https://docs.docker.com/engine/api/v1.45/#tag/Container/operation/ContainerList
Which means the inspect
API endpoint and Docker command do actually return the same information as the containers
return parameter of the module docker_host_info
.