Title: Comment utiliser drone-ci pour tester vos images docker ?
subtitle: (Debian/Ubuntu)
Date: 2017-07-30 08:20
Tags: docker, système, drone-ci, drone
keywords: docker, système, drone-ci, drone
Slug: build-et-test-custom-image-drone-ci
Authors: Victor
Status: published
Summary: Pouvoir tester vos images docker maison et lancer des tests dessus avec drone ? C'est possible !

[TOC]

# Tester Docker avec Docker ?
Dernièrement, je me suis intéressé à [Drone][639feae4] qui est un sympathique logiciel d'[intégration continue][b3aa8892].
Il permet de professionnaliser un peu le fonctionnement d'un dépôt git pour publier automatiquement du code, effectuer des tests divers et variés, envoyer le tout sur un dépot, etc.

Bref, ça permet de faire plus avancé et plus propre que de simples hooks git. Par exemple, pour publier automatiquement ce blog quand je pousse sur mon dépôt :-)

Et l'une des difficultés que j'ai rencontrée, c'est comment tester mes images Docker avec Drone, qui lui même tourne avec Docker.
En effet, ça me paraissait à la fois intéressant et fun de pouvoir oser dans un dépôt git mes images docker, puis lors d'un push construire l'image, vérifier qu'elle se lance, et surtout démarrer des tests sur un exemplaire de l'image elle-même pour être sûr qu'elle fait encore ce pour quoi elle est sensée être faite.

Or, entre la documentation de Drone qui est assez, disons variée, et le fait que le client Drone tourne dans une image docker (ce qui limite les intégrations avec docker lui-même), ça n'était pas si simple.

D'où l'idée de rédiger ce petit article histoire d'avoir une trace en français qui pourrai servir à d'autres personnes intéressées par ce sujet :-)

On va donc voir comment **construire** des images Docker avec Drone, et surtout comment les **lancer** pour les tester !

# Build and Test !
## Prérequis
On va ici partir du principe que ce que vous voulez tester est une image docker.

 * Votre dépot contient donc les fichiers habituels docker et notamment un DockerFile (ou équivalent)
 * Vous avez également Drone installé et configuré pour fonctionner avec votre service git préféré (github, gitlab, gitea et compagnie)
 * Vous avez bien entendu des choses à tester sur votre image ! ;-)
 * Optionnellement, si vous avez un registry Docker, nous verrons comment publier votre image dessus si les tests réussissent

Pour nos tests, nous prendron une image postfix et nous vérifierons que le port 25 répond correctement avec un EHLO kivabien.

## Configuration de Drone
Côté Drone, la configuration est assez simple.

//!\\**Attention tout de même**//!\\ Pour faire tout cela votre drone agent va devoir accéder au socket docker de votre "hyperviseur" Docker.
Il pourra donc, outre construire des images, accéder à toutes les images existantes sur l'hyperviseur. Soit vous le posez dans un hyperviseur avec aucune autre image, soit vous faites très attention à ce que votre système Drone ne soit pas accessible depuis l'extérieur !

Il faut donc autoriser votre drone-agent à accéder au socket docker. Pour ce faire, on va passer par les volumes docker.
Indiquez donc à votre image drone-agent qu'elle peut accéder au socket en lui donnant l'accès, par défaut `/var/run/docker.sock` :

    volumes:  
        - /var/run/docker.sock:/var/run/docker.sock

Puis relancez votre drone-agent à coup de docker-compose.

Celui-ci pourra désormais utiliser les commandes docker pour construire et gérer des images.

## Test de construction
La première chose à vérifier dans la procédure de test est que votre image se construit correctement.

Pour cette phase, on va utiliser comme image Drone une image docker fournie par drone eux-même, et dédié à la construction d'image.
L'astuce va consister à spécifier à la main une commande de build, et ainsi à donner un tag à votre image maison.

Elle va ainsi se retrouver dans le cache local de votre serveur docker, et vous pourrez la réutiliser dans la suite de votre chaine de test pour effectuer des tests dessus !

Voici un exemple de la tache de build :

    build:
      image: docker:latest
      volumes:
        - /var/run/docker.sock:/var/run/docker.sock
      commands:
        - docker build -t test/postfix:latest .

Comme attendu, il faut que le pipeline puisse accéder au socket docker pour la construction de l'image, et ici on place l'image construite dans le dépôt local *test/postfix* avec le tag *latest*.

Vous avez ainsi 2 choses de réalisé :
  * Votre image se construit correctement (c'est toujours ça de pris :-D )
  * Vus disposez d'une version toute fraiche de votre image dans un dépot de test utilisable par Drone

## Test sur l'image
Ensuite, c'est assez simple. Vous allez utiliser votre jolie image toute neuve comme image de base pour votre chaine de test !

Vous pourrez alors lancer tous les tests que vous souhaitez dessus.
Dans mon cas, j'installe quelques outils nécessaires et je lance un script qui va faire un telnet, envoyer un EHLO et vérifier que l'image répond correctement :

    basic_test:
      image: test/postfix:latest
      commands:
        - apt-get update;apt-get install -q -y expect telnet
        - service postfix start
        - ./basic-test.sh

Vous remarquerez que j'ai spécifié pour `image:` le chemin de notre image juste construite.

Si ça vous intéresse, le contenu de `basic-test.sh` :

    #!/usr/bin/expect --

    ## Basic test for postfix
    set timeout 5
    spawn telnet localhost 25
    expect "220 mail.victor-hery.com"
    send -- "EHLO example.com\r"
    expect "250-mail.victor-hery.com"
    send -- "quit\r"
    expect "Bye"

On peut ensuite imaginer toutes sortes de tests bien plus complexes, envoyer un courriel, vérifier qu'il arrive correctement, etc, etc.

On peut aussi utiliser le système de groupe de Drone pour construire plusieurs images simultanéments et faire des tests croisés (par exemple un proxy et un serveur web, une base de données, etc)

## Publier votre image
Si tous vos tests passent avec succès et que vous disposez d'un registry, vous pouvez utiliser le système de publication de Drone à la fin de votre chaine de test :

    publish:
      image: plugins/docker
      tags:
        - latest
      dockerfile: Dockerfile
      volumes:
        - /var/run/docker.sock:/var/run/docker.sock
        - /data/storage/registry/certs/:/etc/ssl/certs
      insecure: true
      repo: registry.local:5000/prod/postfix
      registry: registry.local:5000

Pour ma part il s'agit d'un dépot local à mon serveur, avec un certificat autosigné pour l'instant, d'où les ports maison et le `insecure: true`.

# Limitations
Pour l'instant, la principale limitation à ce genre de chaine de test que j'ai trouvé, c'est l'impossiblité de faire des tests depuis l'extérieur de l'image.

Pour ma part, j'aimerai bien lancer mon image postfix, la binder sur un port, puis m'y connecter pour vérifier comment elle réagit...
De manière plus fine que lancer un test depuis l'intérieur en tablant sur le fait que localhost fonctionnera à l'identique que le bind externe de docker.

J'espère que ce petit article vous plaira, n'hésitez pas à me laisser des commentaires si vous avez des questions, j'y répondrai avec plaisir !
Si vous avez des astuces de votre côté pour utiliser Drone, ce sera également avec grand plaisir que je les consulterai :-)

  [639feae4]: https://github.com/drone/drone "drone continuous integration"
  [b3aa8892]: https://fr.wikipedia.org/wiki/Int%C3%A9gration_continue "Wikipédia fr : intégration continue"
