Oleksandr Gavenko's blog
2020-10-31 00:00 Experimenting with Ansible connection docker

With some luck you can find official documentation online for Docker integration into Ansible:

https://docs.ansible.com/ansible/latest/plugins/connection.html

Connection Plugins.

https://docs.ansible.com/ansible/latest/scenario_guides/guide_docker.html

Docker Guide.

but I lack of description connection docker. Ansible v2.9 supports connection: docker:

$ ansible-doc -t connection -l | grep docker

docker       Run tasks in docker containers

Documentation suggests to read output of:

$ ansible-doc -t connection docker

Run commands or put/fetch files to an existing docker container.
...

Lets start simple Docker container, install software and remove container afterwards.

We will use localhost as the only inventory host:

- hosts: localhost
  connection: local
  become: false
  gather_facts: no

and dynamically add a Docker managed host after creating it:

tasks:

# https://docs.ansible.com/ansible/latest/collections/community/general/docker_container_module.html
# check that container is running by:
#   docker exec alpine-x ps
- docker_container:
    name: alpine-x
    image: alpine:latest
    # command: sh -c "while sleep 1; do :; done"
    command: tail -f /dev/null
    auto_remove: yes
    cleanup: yes
    oom_killer: yes
    state: started

# https://docs.ansible.com/ansible/latest/collections/ansible/builtin/add_host_module.html
- add_host:
    name: alpine-x
    # To avoid: [WARNING]:
    #   Platform linux on host alpine-x is using the discovered Python interpreter at /usr/bin/python3,
    #   but future installation of another Python interpreter could change this.
    ansible_python_interpreter: /usr/bin/python3

Specail trick command: tail -f /dev/null is used to keep container running infinity.

With module add_host we introduce host dynamically of the same name as Docker container.

According to:

https://docs.ansible.com/ansible/latest/reference_appendices/python_3_support.html

Python 3 Support.

we can define Python interpreter only:

To explicitly configure a Python 3 interpreter, set the ansible_python_interpreter inventory variable at a group or host level to the location of a Python 3 interpreter, such as /usr/bin/python3. The default interpreter path may also be set in ansible.cfg.

That is why we see ansible_python_interpreter in add_host.

On other hand we can avoid setting ansible_connection & ansible_ssh_user:

- add_host:
    name: alpine-x
    ansible_connection: docker
    ansible_ssh_user: root

on add_host level because those settings are supported at plays' hosts settings connection & user:

- hosts: alpine-x
  connection: docker
  user: root
  become: false
  gather_facts: no
  # vars:
  #   ansible_python_interpreter: /usr/bin/python3

  tasks:

  # https://docs.ansible.com/ansible/latest/collections/ansible/builtin/raw_module.html
  - raw:
      apk add python3

  # https://docs.ansible.com/ansible/latest/collections/community/general/apk_module.html
  - apk:
      name: mc
      state: present

Still ansible_python_interpreter could be defined at vars section.

We have to install Python 3 with module row as Alpine images don't have them bundled. Then we can use Ansible modules as usual (apk is an example).

https://wiki.alpinelinux.org/wiki/Ansible

Managed nodes. There are only minimal requirements for the clients. For every system you want to manage, you need to have the client's SSH key in the authorized_keys file of the management system and Python.

https://wiki.alpinelinux.org/wiki/Ansible_APK_Module

Ansible APK Module.

Finally we can destroy running container (remember tail -f /dev/null blocks termination!):

- hosts: localhost
  connection: local
  become: false
  gather_facts: no

  tasks:

  # https://docs.ansible.com/ansible/latest/collections/community/general/docker_container_module.html
  # check that container is stopped:
  #   docker ps
  - docker_container:
      name: alpine-x
      image: alpine:latest
      state: absent

Check full example play-fun-with-docker.yml.

Run it as:

ansible-playbook  play-fun-with-docker.yml

Of cause you need to have Ansible & Docker installed and Docker supervisor running ))

You can communicate with Docker directly (here raw module is used, don't forget to start container $NAME beforehand):

$ id=$(docker run -d --name alpine alpine tail -f /dev/null)

$ ansible all -i "alpine," -c docker -m raw -a 'echo OK'
$ ansible all -i "$id," -c docker -m raw -a 'echo OK'

$ docker stop alpine
$ docker stop $id
ansible

Feeds

all / emacs / java

Tags

adb(1), admin(1), android(1), anki(1), ansible(2), aop(1), blog(2), bytecode(1), c(1), css(2), cygwin(2), driver(1), emacs(3), fs(1), git(3), google(1), gradle(1), hardware(1), hg(2), html(1), interview(13), java(4), js(3), lang(2), lighttpd(1), markdown(1), mobile(1), naming(1), oracle(1), print(1), problem(5), python(1), quiz(6), rst(2), security(3), spring(2), sql(2), srs(1), style(1), tls(2), txt(1), unit(1), utils(1), vcs(3), web(2), win(2), windows(1)

Archive