Sommaire
Mettre en place des build automatiques avec jenkins et docker
L'intégration continue, c'est vachement bien, mais parfois, c'est un peu compliqué à mettre en place.
Ce journal explique comment mettre en place un serveur de build automatiques maison.
L'intérêt est d'avoir une solution locale qui permet de compiler sur un réseau local (en entreprise par exemple où l'accès à Internet est parfois compliqué et où on a rarement envie d'utiliser des services externes)
Ici je vais détailler commente compiler régulièrement des projets utilisant gcc
et automake
.
Outils
Pour réaliser tout ça, on a utilisé :
- Ubuntu 14.04
- docker 1.6.2
- jenkins 2.150.2
- alpine 3.7
installation de docker
On commence par installer docker, pour ça pas de mystère, on tape :
$sudo apt-get install docker.io
Une fois docker installé, on permet à l'utilisateur lambda de l'utiliser :
$sudo addgroup docker
$sudo usermod -aG docker $USER
On se déconnecte/reconnecte et on peut tester que tout fonctionne :
docker run hello-world
installation de jenkins
On lance une image jenkins :
$docker run --name jenkins-master -d -p 8080:8080 -p 50000:50000 -v /var/jenkins_home jenkins/jenkins:lts
Explication de la commande :
-
docker run
: on lance une image -
--name jenkins-master
: on lui donne un nom -
-d
: en arrière plan -
-p x:y
: le porty
de la machine virtuelle est mappée sur le portx
de l'hote -
-v chemin
: on crée un volume pour garder les données de jenkins -
jenkins/jenkins:lts
: nom de l'image à utiliser (prise depuis hub.docker.com)
Une fois la machine lancée, on peut lancer un navigateur web et se connecter sur 127.0.0.1:8080
.
Après quelque temps, jenkins est prêt à être configuré. La première chose qu'il demande, est le mot de passe initial, pour cela, on demande à docker de nous récupérer un fichier dans la machine jenkins :
Il faut alors copier le contenu du fichier
$docker cp jenkins-master:/var/jenkins_home/secrets/initialAdminPassword .
initialAdminPassword
dans la page web qui la demandait.
Il est alors demandé de sélectionner les plugins à installer, on peut garder les réglages par défaut.
On entre les informations de l'administrateur, et surtout, on clique sur "save & continue".
On définit enfin à quelle adresse sera accessible le serveur.
Jenkins est prêt à être utilisé.
Création d'un agent SSH
Maintenant, on va créer une seconde machine docker qui sera en charge de compiler notre projet.
création d'un esclave ssh
Identification des besoins
Dans un projet, on identifie ce dont on a besoin, ici je prends un vieux projet perso : txt2snd
Pour la construction, on aura besoin de :
- gcc et une lib-c
- make, automake et autoconf
- libsndfile
Fort de ces informations, on peut créer un fichier Dockerfile
qui pourra compiler le projet et interagir avec le maitre jenkins
# on part d'une image alpine
FROM alpine:3.7
# on ajoute openssh pour la connexion ssh
# et openjdk qui est requis par jenkins
RUN apk add openssh openjdk8-jre-base
# on ajoute git pour accéder au repo
RUN apk add git
# gcc et make
RUN apk add gcc make
# et enfin les bibliothèques dont le projet a besoin
RUN apk add libc-dev libsndfile-dev
# un peu de configuration
# un script pour générer des clefs ssh
COPY ssh-slave-entrypoint.sh /usr/bin/
# en le rendant executable (est-ce bien nécessaire ?)
RUN chmod +x /usr/bin/ssh-slave-entrypoint.sh
# on efface d'éventuels anciennes clefs (même remarque)
RUN rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key
# on crée un utilisateur
RUN adduser -D jenkins
# auquel on ajoute un mot de passe
RUN echo "jenkins:jenkins" | chpasswd
# et on crée un répertoire pour ranger le bazard jenkins
RUN mkdir /home/jenkins/jenkins_slave
# que l'on donne à l'utilisateur
RUN chown jenkins /home/jenkins/jenkins_slave
# on ouvre le port 22 pour ssh
EXPOSE 22
# on définit le script copié plutôt comme le point d'entrée
ENTRYPOINT ["ssh-slave-entrypoint.sh"]
# et on lance le serveur ssh au démarrage de la machine
CMD ["/usr/sbin/sshd", "-D"]
Le fichier ssh-slave-entrypoint.sh
contient lui
#!/bin/sh
if [ ! -f "/etc/ssh/ssh_host_rsa_key" ] ; then
ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
fi
if [ ! -f "/etc/ssh/ssh_host_dsa_key" ] ; then
ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa
fi
if [ ! -d "/var/run/sshd" ]; then
mkdir -p /var/run/sshd
fi
exec "$@"
Ce script là, je l'ai pris du dépot alpine-sshd.
On construit l'image :
Avec :
$docker build -t gcc.slave .
-
docker build
: on crée une nouvelle image -
-t gcc.slave
: qu'on appelle 'gcc.slave' -
.
: on prend deDockerfile
du dossier courant
Et on lance cette image, en redirigeant le port 22 sur le 2222 :
On peut maintenant dire à jenkins d'utiliser cette image.
$docker run -d --name gcc.slave -p 2222:22 gcc.slave
ajout de l'esclave à jenkins
On se rend à la page 127.0.0.1:8080/computer/new
pour créer un nouveau noeud.
Une fois dans la page http://127.0.0.1:8080/computer/createItem
, on configure :
- le nom de l'agent, ici
gcc.slave
- le nom du répertoire de travail (Remote root directory),
ici
/home/jenkins/jenkins_slave
- l'adresse de l'agent (qu'on récupère avec
ifconfig
) - les droits d'accès (ici jenkins/jenkins)
- la stratégie de vérification, ici on vérifie rien
- le port ssh (dans le menu avancé), ici 2222
On enregistre le tout et sur la page 127.0.0.1:8080/computer/gcc.slave/
, on lance l'agent.
L'agent est lancé ? Alors on peut configurer le projet.
configuration du projet à construire
Sur la page 127.0.0.1:8080/newJob
, on créé le projet txt2snd
de type Freestyle project
Puis on le configure :
- Dans "General"
- On sélectionne "Restrict where this project can be run" et indiquer le nom de l'agent ssh à utiliser si on a plusieurs projets et plusieurs agents
- Dans "Source Code Management", on sélectionne "Git"
- On indique l'URL du dépot :
https://framagit.org/mabu/txt2snd.git
- On indique l'URL du dépot :
- Dans "Build Triggers"
- Des build périodique
- Qu'on programme tous les jours à midi :
H 12 * * *
- Dans "Build"
- On ajoute "execute shell", avec pour code : #!/bin/sh autoreconf --install ./configure make
On enregistre.
Et on tente de lancer le build: 127.0.0.1:8080/job/txt2snd/build?delay=0sec
(il y a un bouton pour ça).
Et finalement, le programme est compilé. On peut aller chercher les fichiers construits dans 127.0.0.1:8080/job/txt2snd/ws/
Et après
Dans cet article, je suis passé un peu vite sur la sécurisation des agents, dans le cadre d'un réseau isolé, c'est pas bien grave, mais il faut garder à l'esprit que j'ai un peu bâclé cette partie.
Après, on peut aller plus loin, on peut imaginer avoir un agent sur une machine réelle qui puisse exécuter d'autres outils de compilation ou même des systèmes de tests maisons.
On peut aussi changer de SCM, envoyer des mails en cas d'échec, déployer…
Les possibilités semblent illimitées.
# drone.io
Posté par woffer 🐧 . Évalué à 4.
Hello,
Quelqu'un a-t-il déjà essayé drone?
[^] # Re: drone.io
Posté par stan_linux . Évalué à 7. Dernière modification le 10 février 2019 à 18:20.
Salut,
J'ai testé drone. C'est vraiment pas mal et surtout super léger. Au final je suis passé sur GitLab CI avec mon propre runner pour build et push mes images Docker. Je trouve GitLab CI plus flexible et je préfère la syntaxe.
[^] # Re: drone.io
Posté par damaki . Évalué à 4. Dernière modification le 10 février 2019 à 20:01.
Ça donne quoi Gitlab CI en termes de RAM ? Parce que Gitlab tout court prend déjà 2 Go de RAM de base et donc c'est déjà du gâchis de ressources pour une petite install.
J'suis aussi en quête d'un outil de meilleure qualité que Jenkins (le Eclipse de l'intégration continue) et au moins aussi léger. Puis avec une intégration Docker de meilleure qualité. J'arrive toujours pas à comprendre l'absence de client docker dans les images officielles du master ; j'ai du bricoler ça moi même.
[^] # Re: drone.io
Posté par woffer 🐧 . Évalué à 1.
Les runners de gitlab ci sont écrits en Go. Donc, j'imagine que ça ne doit pas prendre beaucoup de RAM.
[^] # Re: drone.io
Posté par phoenix (site web personnel) . Évalué à 2.
En perso j'utilise le couple gîtes + drone.
C'est très léger et ça fonctionne bien.
[^] # Re: drone.io
Posté par oau . Évalué à 4.
Bonjour,
ici nous utilisons gitlab depuis 4ans. Oui ça prend un peu de ram. 3go pour une instance avec une douzaine de projet actif et autant de développeur/datascientist. Un peu de disque. (Surtout quand on me commit tout anaconda ….). Les mises à jour sont régulières via un dépôt apt et elles sont fiables. Je n'ai eu en 4ans qu'un seul problème de mise à jour.
Depuis quelques mois nous utilisons aussi gitlab ci avec un kubernetes auto hébergé. Et bien ça change la vie ! Je crée une branche et j'ai de suite un environnement qui tourne sur cette branche avec un snapshot des données de la prod (merci ceph !) et une url dédié. Je fait ma modif. La QA la valide. La branche est merge et tout passe en prod tout seul. Plus de script de mise en production, plus de "jour de mise en prod". Bref on a plongé dans le grand bain du devops, cloud, container etc.
A titre personnel j'étais plus que réticent. Je regarde ces technos du coin de l’œil depuis des années avec scepticisme et finalement j'en suis très content.
Cependant il y a un soucis de cache avec le gitlab runner et le build d'image docker qui est très long. Vu que chaque stage est dans un environnement docker tout neuf (dind) il n'y a pas de mise en cache des différentes étapes de build. Je dois donc maintenir une image de base avec tout ce qui est nécessaire. Image que j'utilise ensuite juste pour copier le code de l'application et la conf.
Pour vous donner une idée il faut environ deux minutes pour démarrer 6 pod qui contiennent un minimum de deux container (j'utilise istio) et jusqu’à 4 container. Pour un total d'environ 15 container. Il y a aussi le snapshot de la base postgres et son démarrage.
[^] # Re: drone.io
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
gitlab CI est disponible en service ou faut-il le gérer soi-même à la main ?
"La première sécurité est la liberté"
[^] # Re: drone.io
Posté par Moonz . Évalué à 3.
C’est ce que j’utilise. S’intègre bien avec gitea.
Il y a aussi : https://sourcehut.org/
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.