Integración entre Ansible y Docker

Escrito por el , actualizado el .
gnu-linux planeta-linux planeta-codigo blog-stack
Comentarios

Ansible
Docker

En la introducción de Docker y inicio básico de docker explicaba como usar Docker y en la introducción a Ansible explicaba las características de Ansible y como usarlo. Podemos usar Docker y Ansible de forma separada pero también podemos combinarlas para beneficiarnos de las propiedades de cada una. En Ansible disponemos de dos módulos que nos permite manejar las imágenes y los contenedores de Docker, estos son docker y docker_image.

Usando tareas de ansible podemos automatizar el arranque del servicio de docker, la construcción de las imágenes con los Dokerfile y el inicio o parada de los contenedores de docker. En el ejemplo se construye una imagen base en la que se basarán el resto de imágenes, se crea una imagen con mysql, otra de redis y finalmente la imagen apps donde se ejecutarán las aplicaciones que usarán los servicios de mysql y redis.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
---
- hosts: devbox
    - name: start docker service
      service: name=docker state=started
      sudo: true
   
    - name: build docker images
      docker_image: name="{{ item.name }}" tag="{{ item.tag }}" state="present" path={{ item.path }}
      with_items:
      - { name: "picodotdev/base", tag: "1.0", path: "../docker/base" }
      - { name: "picodotdev/mysql", tag: "1.0", path: "../docker/mysql" }
      - { name: "picodotdev/redis", tag: "1.0", path: "../docker/redis" }
      - { name: "picodotdev/apps", tag: "1.0", path: "../docker/apps" }

Una vez que disponemos de las imágenes de docker podemos arrancar contenedores con ellas automatizándolo con ansible. En este caso se inicia el servicio de docker, se inicializan los contenedores con los volúmenes donde se guardan los datos de forma persistente de mysql y redis, se inician los contenedores de mysql y redis usando los volúmenes anteriores y finalmente el contenedor de las aplicaciones. Al final, se muestra cierta información de las imágenes como sus direcciones IP.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
- hosts: devbox
  tasks:
    - name: start docker service
      service: name=docker state=started
      sudo: true

    - name: start mysql data docker container
      docker: image=busybox:latest name=picodotdev-mysql-data state=present volumes="/var/lib/mysql"
      register: mysql_data_container

    - name: start redis data docker container
      docker: image=busybox:latest name=picodotdev-redis-data state=present volumes="/var/lib/redis"
      register: redis_data_container

    - name: start mysql docker container
      docker: image=picodotdev/mysql:1.0 name=picodotdev-mysql state=running volumes_from=picodotdev-mysql-data hostname=mysql ports=3306:3306 command=/sbin/my_init
      register: mysql_container

    - name: start redis docker container
      docker: image=picodotdev/redis:1.0 name=picodotdev-redis state=running volumes_from=picodotdev-redis-data volumes="{{ keys_path }}:/mnt/keys" hostname=redis ports=6379:6379 command=/sbin/my_init
      register: redis_container

    - name: start apps docker container
      docker: image=picodotdev/apps:1.0 name=picodotdev-apps state=running volumes="{{ projects_path }}:/mnt/projects,{{ grails_path }}:/root/.grails,{{ gradle_path }}:/root/.gradle,{{ keys_path }}:/mnt/keys" hostname=apps ports=8080:8080,8443:8443 links=picodotdev-mysql:mysql,picodotdev-redis:redis command=/sbin/my_init
      register: apps_container

    - name: update hosts with containers ip address
      replace: dest=/etc/hosts regexp="^(\d+\.\d+\.\d+\.\d+)(\s+{{ item.host }})$" replace="{{ item.ip }}\2"
      sudo: true
      with_items:
      - { host: "mysql", ip: "{{ mysql_container['ansible_facts']['docker_containers'][0]['NetworkSettings']['IPAddress'] }}" }
      - { host: "redis", ip: "{{ redis_container['ansible_facts']['docker_containers'][0]['NetworkSettings']['IPAddress'] }}" }
      - { host: "apps", ip: "{{ apps_container['ansible_facts']['docker_containers'][0]['NetworkSettings']['IPAddress'] }}" }

    - name: display containers info
      debug: msg="info"
      with_items:
      - { name: "{{ mysql_container['ansible_facts']['docker_containers'][0]['Name'] }}", ip: "{{ mysql_container['ansible_facts']['docker_containers'][0]['NetworkSettings']['IPAddress'] }}", id: "{{ mysql_container['ansible_facts']['docker_containers'][0]['Id'] }}" }
      - { name: "{{ redis_container['ansible_facts']['docker_containers'][0]['Name'] }}", ip: "{{ redis_container['ansible_facts']['docker_containers'][0]['NetworkSettings']['IPAddress'] }}", id: "{{ redis_container['ansible_facts']['docker_containers'][0]['Id'] }}" }
      - { name: "{{ apps_container['ansible_facts']['docker_containers'][0]['Name'] }}", ip: "{{ apps_container['ansible_facts']['docker_containers'][0]['NetworkSettings']['IPAddress'] }}", id: "{{ apps_container['ansible_facts']['docker_containers'][0]['Id'] }}" }

Ansible dispone muchos módulos que nos permiten automatizar las tareas: