Ansible w/ Docker - Show current Container state

This worked for me:

    - name: Get container status
      shell: docker inspect --format={{ '{{.State.Running}}' }} {{ container_name }}
      register: status
    #Start the container if it is not running
    - name: Start the container if it is in stopeed state.
      shell: docker start heuristic_mestorf
      when: status.stdout != "true"

Unfortunately, none of the modules around docker can currently "List containers". I did the following as work around to grab the status:

- name: get container status
  shell: docker ps -a -f name={{ container }} --format {%raw%}"table {{.Status}}"{%endraw%} | awk 'FNR == 2 {print}' | awk '{print $1}'
  register: status

Result will then be available in the status variable


As of Ansible 2.8 you can use the docker_container_info, which essentially returns the input from docker inspect <container>:

- name: Get infos on container
  docker_container_info:
    name: my_container
  register: result

- name: Does container exist?
  debug:
    msg: "The container {{ 'exists' if result.exists else 'does not exist' }}"

- name: Print the status of the container
  debug:
    msg: "The container status is {{ result.container['State']['Status'] }}"
  when: result.exists

With my Docker version, State contains this:

"State": {
    "Status": "running",
    "Running": true,
    "Paused": false,
    "Restarting": false,
    "OOMKilled": false,
    "Dead": false,
    "Pid": 8235,
    "ExitCode": 0,
    "Error": "",
    "StartedAt": "2019-01-25T14:10:08.3206714Z",
    "FinishedAt": "0001-01-01T00:00:00Z"
}

See https://docs.ansible.com/ansible/2.8/modules/docker_container_info_module.html for more details.


Edit: If you are running Ansible 2.8+ you can use docker_container_info. See David Pärsson's answer for details.

Here is one way to craft it using the docker_container module (note that it will create the container if it does not exist):

- name: "Check if container is running"
  docker_container:
    name: "{{ container_name }}"
    state: present
  register: container_test_started
  ignore_errors: yes

- set_fact:
    container_exists: "{{ container_test_started.ansible_facts is defined }}"

- set_fact:
    container_is_running: "{{ container_test_started.ansible_facts is defined and container_test_started.ansible_facts.docker_container.State.Status == 'running' }}"
    container_is_paused: "{{ container_test_started.ansible_facts is defined and container_test_started.ansible_facts.docker_container.State.Status == 'paused' }}"

For me the gotchya was that if the container doesn't exist, ansible_facts is not defined. If it does though, then that contains basically the whole docker inspect <container> output so I navigate that for the status.

If you just need to short circuit, a simpler alternative would be to move the desired set_fact'd value into a failed_when on the docker_container task.

I do it through set_fact to keep my options open for forking behavior elsewhere.. e.g. stop, do task, then put back how it was.

I included pause because it is commonly forgotten as a state :)