Installation de Teamcity avec Docker

Teamcity est un serveur de build très puissant et assez flexible. Avec Jenkins et Travis, il fait partie des outils les plus utilisés pour faciliter la mise en place de pratiques d’intégration continue. Teamcity est implémenté en Java toutefois il s’adapte et peut facilement être utilisé pour de très nombreuses technologies comme, par exemple, .NET.

Contrairement à Travis et à Jenkins, Teamcity n’est pas entièrement gratuit, toutefois la licence permet de configurer gratuitement 20 configurations de builds (i.e. build configuration) et 3 agents, ce qui est suffisant pour la plupart des cas d’utilisation. Teamcity peut être installé sur Windows, Linux ou MacOS. Même si le serveur Teamcity est installé sur une machine avec un OS spécifique, il peut s’interfacer avec d’autres machines qui peuvent être dans des OS différents de façon à piloter des builds avec des technologies différentes. Un même serveur Teamcity peut donc effectuer des builds dans des technologies différentes.

Dans cet article, on se propose d’expliquer l’installation d’un serveur Teamcity. Dans un article futur, je présenterai les fonctionnalités principales de Teamcity de façon à être capable de configurer une chaine de build complète.

La documentation de Teamcity est bien faite et très complète. Le but de cet article n’est pas de paraphraser la documentation de l’éditeur mais de permettre de monter rapidement un serveur Teamcity, de comprendre rapidement les fonctionnalités les plus importantes et de se familiariser avec l’interface de Teamcity pour être capable de l’utiliser efficacement. Cet outil est facile à utiliser toutefois il possède énormément de fonctionnalités qui ne sont pas faciles à appréhender aux premiers abords.

Dans un premier temps, on indiquera une méthode pour installer un serveur Teamcity sur une machine Linux avec Docker, ensuite on configurera un build agent et enfin on indiquera quelques éléments de configuration intéressants sur le serveur de build.

L’intérêt d’installer Teamcity en utilisant l’image Docker, est d’avoir une procédure d’installation rapide qui permet une grande flexibilité puisqu’on peut facilement supprimer l’image et reprendre l’installation.

Il n’est pas obligatoire de passer par Docker pour installer Teamcity

On peut aussi installer directement Teamcity sur d’autres OS comme Linux, Windows ou macOS. Dans le cas où on ne souhaite pas polluer son système d’exploitation avec une installation qui ne sert que pour effectuer un test, on peut aussi installer Debian sur une machine virtuelle VirtualBox et installer Teamcity sur la Debian.

Installation préalable de Docker

Avant d’installer Teamcity, il faut installer Docker pour pouvoir exécuter l’image.

Dans notre cas, on souhaite installer Docker Community Edition (i.e. Docker CE) sur un système Debian 9 (Stretch). On peut toutefois installer facilement Docker CE sur d’autres systèmes d’exploitation.

Sur Debian 9, il faut suivre les instructions suivantes: Get Docker CE for Debian.

Dans notre cas, Debian 9 (Stretch) concerne la partie “Jessie or newer” (Jessie correspond à Debian 8) dans la documentation de Teamcity.

Après l’installation, pour éviter d’exécuter l’image Docker avec l’utilisateur root, on peut créer un utilisateur simple qui aura l’autorisation d’exécuter une image Docker. Cette configuration est facultative mais permet de séparer les responsabilités.

On peut créer un utilisateur et l’ajouter au groupe docker en exécutant en tant qu’utilisateur root la comande:

root@debian:~% adduser --ingroup docker dockeruser

On peut voir que l’utilisateur dockeruser appartient au groupe docker en exécutant:

root@debian:~% groups dockeruser 

L’utilisateur dockeruser peut maintenant exécuter une commande docker.

Erreur “permission denied” quand on tente d’exécuter une image Docker

Si on tente d’exécuter une image Docker avec un utilisateur qui n’appartient pas au groupe docker, on aura une erreur du type:

Got permission denied while trying to connect to the Docker daemon socket
at unix:///var/run/docker.sock

Ceci s’explique par le fait que la lecture ou l’écriture de /var/run/docker.sock nécessite d’appartenir au groupe docker. On peut s’en rendre en compte en exécutant:

root@debian:~% ls -al /var/run/docker.sock

On obtient:

srw-rw---- 1 root docker 0 Sep 12 00:04 /var/run/docker.sock

Pour résoudre ce problème, il suffit d’ajouter l’utilisateur au groupe docker en exécutant:

root@debian:~% usermod -aG docker <alias de l'utilisateur>

Il faut ensuite redémarrer pour que l’ajout de l’utilisateur au groupe soit pris en compte:

root@debian:~% reboot

Executer l’image Teamcity

D’abord, on crée des répertoires pour partager avec le container des données relatives au serveur Teamcity:

dockeruser@debian:~% mkdir /home/dockeruser/teamcity 
dockeruser@debian:~% mkdir /home/dockeruser/teamcity/data 
dockeruser@debian:~% mkdir /home/dockeruser/teamcity/logs

Pour créer un container à partir de l’image Docker de Teamcity (sur docker hub) il faut exécuter la commande:

dockeruser@debian:~% docker run -it --name teamcity-server-instance \  
  -v /home/dockeruser/data:/data/teamcity_server/datadir \  
  -v /home/dockeruser/logs:/opt/teamcity/logs \  
  -p 8111:8111 \  
  jetbrains/teamcity-server

Le détail des options est:

  • -it: permet de démarrer le processus dans le container en attachant la console de l’hôte de façon à ce que les entrées standard, les sorties standard et les erreurs de la console du container soient visibles dans la console de l’hôte.
  • --name <nom du container>: permet d’indiquer le nom du container dans lequel sera exécuté l’image Docker.
  • -v /home/dockeruser/data:/data/teamcity_server/datadir: permet de partager le contenu du répertoire /home/dockeruser/data de l’hôte avec le répertoire /data/teamcity_server/datadir du container. Le répertoire de données du container sera ainsi plus facilement accessible sur l’hôte.
  • -v logs:/opt/teamcity/logs: permet de partager le contenu du répertoire /home/dockeruser/logs de l’hôte avec le répertoire /opt/teamcity/logs du container. Cette option permet d’accéder facilement au répertoire de logs du container à partir de l’hôte.
  • -p 8111:8111: indique que le port 8111 de l’hôte sera redirigé vers le port 8111 du container Docker.
Ouvrir un bash dans le “container”

On peut ouvrir un bash dans le container Docker en exécutant:

dockeruser@debian:~% docker exec –it teamcity-server-instance /bin/bash

Relancer l’exécution du container

Si l’image a déjà été exécutée dans un container avec le nom “teamcity-server-instance” et si on relance la commande précédente:

dockeruser@debian:~% docker run -it --name teamcity-server-instance ...

On peut obtenir une erreur du type:

docker: Error response from daemon: Conflict. The container name 
"/teamcity-server-instance" is already in use by container 
"ab19821b4d64fb0e221b0a2c898db1745703acb45b96d602caddc3f6b25bfa5c". You have to remove 
(or rename) that container to be able to reuse that name. 
See 'docker run --help'.

Cette erreur signifie que le container se nommant “teamcity-server-instance” existe déjà. Pour relancer l’exécution de ce container, il suffit d’exécuter la commande:

dockeruser@debian:~% docker start teamcity-server-instance

Si le serveur Teamcity est correctement démarré, on peut se connecter avec un browser à l’adresse suivante:

http://localhost:8111

Stopper l’exécution du container

De même pour stopper l’exécution du container et par suite du serveur Teamcity, il faut taper:

dockeruser@debian:~% docker stop teamcity-server-instance

Configuration du serveur Teamcity

On peut accéder à l’interface en se connectant avec un browser à l’adresse:

http://localhost:8111

On doit obtenir un écran du type:

Teamcity First Start

En cliquant sur “Proceed”, on peut choisir un type de base de données, dans notre cas, on choisit “Internal (HSQLDB)”:

Teamcity Database connection setup

Il faut ensuite répondre à quelques questions avant d’arriver à la création d’un utilisateur avec des droits d’administrateur:

Teamcity Création administrateur

On arrive ensuite sur l’interface principale de Teamcity:

Ecran principal

Versionner la configuration de Teamcity

Teamcity a une fonctionnalité particulièrement intéressante qui permet de versionner la configuration des projets dans un gestionnaire de version (comme SVN ou Git). Cette étape est facultative. Avec cette fonctionnalité, la synchronisation se fait dans les 2 sens:

  • Teamcity commit lui-même les changements dans le gestionnaire de versions à chaque changement de la configuration.
  • Si on modifie la configuration dans le gestionnaire de versions en éditant les fichiers, Teamcity rechargera automatiquement sa configuration après le commit des modifications.

L’intérêt de cette fonctionnalité est de:

  • Pouvoir revenir en arrière facilement dans la configuration si on a fait une erreur,
  • Importer facilement une configuration sur on installe un nouveau serveur,
  • Voir la configuration avec des outils comme Github.
  • Editer directement la configuration dans les fichiers versionnés

Pour effectuer cette configuration à partir de l’interface de Teamcity, il faut cliquer sur “Administration”:

Cliquez sur “Administration”

Puis sur “<Root project>”:

Cliquez sur “<Root project>”

Dans le menu de gauche, il faut cliquer sur “VCS Roots” pour ajouter une configuration pour un gestionnaire de version (VCS signifie “Version Control System”):

Cliquez sur “VCS Roots”

On clique ensuite sur “Create VCS root” et on indique les paramètres d’accès au VCS:

Cliquez sur “Create VCS root”

Dans notre cas, on utilise GitHub. On a donc créé un compte sur GitHub puis un repository de façon à indiquer ces paramètres dans Teamcity.

Si à ce moment, on essaie d’effectuer un test de connexion en cliquant sur “Test connection”, on aura un message d’erreur:

Cannot find revision of the default branch 'refs/heads/master' of vcs root 
"jetbrains.git" {instance id=10, parent internal id=-1, parent id=dummy_jetbrains.git, 
description: "https://github.com/teamcitytest/teamcityconfig.git#refs/heads/master"}

Cette erreur est due au fait qu’il n’existe pas de branche “master” sur le repository. Pour créer une branche vide, il suffit de créer un fichier README.md sur GitHub et la branche “master” sera créée.

Ne pas confondre le versionnement de la configuration Teamcity et l’accès au “repository” d’un projet

Dans le cas présent, on a configuré un repository pour permettre de versionner la configuration de Teamcity. Le repository de la configuration est différent du repository d’un projet pour lequel on souhaiterait effectuer une build.

Le repository contenant la configuration de Teamcity est mis à jour directement par Teamcity. On peut le voir si on regarde dans GitHub dans le répertoire .teamcity.

Dans notre cas, le repository est teamcityconfig.

Enfin dans Teamcity, il faut indiquer à Teamcity quel est le paramétrage de gestionnaire de version qui permet de stocker la configuration. On clique donc sur “Versioned Settings” dans le menu à gauche:

Ecran “Versioned Settings”

Puis:

  1. On sélectionne “Synchronization enabled”
  2. On sélectionne le paramétrage de VCS Root qui correspond à la configuration,
  3. On sélectionne “use settings from VCS”.
  4. On valide en cliquant sur “Apply”.
    Ecran “Versioned Settings”

A la fin de cette étape, Teamcity effectue directement des modifications dans le repository GitHub et les commit.

Installation d’un agent Teamcity

Un agent Teamcity est une machine sur laquelle sera exécutée les différentes builds. Cette machine peut être différente de celle qui héberge le serveur Teamcity. Teamcity permet d’utiliser plusieurs agents avec des architectures différentes. L’intérêt d’avoir plusieurs agents est de:

  • Pouvoir effectuer des builds dans des architectures et des technologies différentes,
  • Paralléliser les builds sur plusieurs agents.
  • Avoir un seul serveur Teamcity qui s’interface avec plusieurs agents, la configuration reste ainsi centralisée.

Comme indiqué plus haut, l’agent peut se trouver sur une autre machine que celle du serveur Teamcity. Dans notre cas, pour simplifier, l’agent se trouvera sur la même machine.

Pour installer l’agent Teamcity, il faut cliquer en haut de l’interface d’administration de Teamcity sur “Agents” puis à droite sur “Install Build Agents”:

Cliquez sur “Install Build Agents”

On télécharge le fichier correspondant à l’architecture sur laquelle on veut installer l’agent. Dans notre cas, on cliquer sur “Zip file distribution” puisqu’on souhaite installer l’agent sur une machine Linux.

On décompresse le fichier en exécutant les commandes suivantes:

dockeruser@debian:~% mkdir /home/dockeruser/teamcity_agent 
dockeruser@debian:~% unzip /home/dockeruser/buildAgent.zip -d /home/dockeruser/teamcity_agent

Ensuite, on copie le répertoire dans le répertoire /usr en tant qu’utilisateur root:

root@debian:~% cp –r /home/dockeruser/teamcity_agent /usr

On change les autorisations du répertoire pour que l’utilisateur dockeruser puisse exécuter l’agent:

root@debian:~% chown -r dockeruser:docker /usr/teamcity_agent

Pour plus d’informations sur l’installation d’un agent Teamcity, on peut se reporter à la documentation de JetBrains.

Installation de JAVA

Avant de lancer l’agent Teamcity, il faut installer une JRE sur la machine si ce n’est pas déjà fait.

On peut télécharger la JRE sur le site d’Oracle: http://www.oracle.com/technetwork/java/javase/downloads/index.html.

Dans notre cas, la version utilisée était la jdk1.8.0_151 pour linux en 64 bits.

On peut installer la JRE sur le disque en exécutant:

root@debian:~% tar zxvf jdk-8u151-linux-x64.tar.gz

Cette commande permet d’extraire les fichiers contenus dans l’archive en listant tous les fichiers extraits.

En tant qu’utilisateur root, il faut placer le répertoire résultant dans /usr/java

root@debian:~% mkdir /usr/java  
root@debian:~% mv <nom du répertoire> /usr/java

Ensuite, il faut ajouter la variable d’environnement JRE_HOME dans le PATH en éditant le fichier /etc/profile en tant qu’utilisateur root:

root@debian:~% vi /etc/profile

On ajoute ensuite les lignes suivantes à la fin du fichier (pour passer en mode édition dans vi, il faut appuyer sur la touche [i]):

export JRE_HOME="/usr/java/jdk1.8.0_151/jre" 
export PATH=$JRE_HOME/bin:$PATH

On enregistre en tapant [Echap] puis :wq.

Configuration de l’agent

On configure l’agent Teamcity en tapant les commandes suivantes:

  1. On renomme le fichier buildAgent.dist.properties en buildAgent.properties:
    dockeruser@debian:~% mv /usr/teamcity_agent/conf/buildAgent.dist.properties /usr/teamcity_agent/conf/buildAgent.properties
    
  2. On édite, ensuite ce fichier en tapant:
    dockeruser@debian:~% vi /usr/teamcity_agent/conf/buildAgent.properties
    

    (Pour passer en mode édition dans vi, il faut appuyer sur la touche [i])

  3. Si on installe l’agent sur une machine différente de celle sur laquelle se trouve le serveur Teamcity, il faut modifier le paramètre serverUrl pour qu’il pointe vers le serveur Teamcity:
    serverUrl=http://<adresse IP du serveur Teamcity>:8111/
    

    Dans le cas contraire, on peut laisser la valeur:

    serverUrl=http://localhost:8111/
    
  4. Il faut ensuite indiquer le nom de l’agent avec le paramètre name:
    name=BuildAgent1
    

    On enregistre en tapant [Echap] puis :wq.

Démarrage de l’agent

Une fois que la configuration est effectuée, on peut démarrer l’agent en exécutant:

dockeruser@debian:~% ./usr/teamcity_agent/bin/agent.sh start

Les logs sont consultables dans le répertoire:

/usr/teamcity_agent/logs

Si le démarrage s’est effectué correctement, on devrait voir dans le fichier /usr/teamcity_agent/logs/teamcity-agent.log une phrase du type:

Updating agent parameters on the server

Ajout de l’agent à la configuration Teamcity

A la fin de l’étape précédente, après quelques secondes, l’agent doit apparaître dans l’interface de Teamcity en cliquant sur “Agents” en haut à gauche puis sur l’onglet “Unauthorized”:

Cliquez sur “Agents” puis “Unauthorized”

Il faut cliquer sur le nom de l’agent puis sur “Authorize agent”:

Cliquez sur “Authorize agent”

Après cette étape, l’agent est connecté avec le serveur Teamcity.

Configurer les “clean-up rules”

Ce paramétrage est particulièrement traitre dans Teamcity car, par défaut, Teamcity conserve tous les fichiers résultats des builds sur le serveur. La conservation de ces fichiers saturent rapidement la mémoire du serveur en particulier si on effectue souvent des builds et si on possède beaucoup de configurations de build.

Les “clean-up rules” sont des règles permettant d’indiquer quand supprimer ces fichiers.

Pour accéder au paramétrage des “clean-up rules”, il faut:

  1. Cliquer sur “Administration”
  2. Puis cliquer sur <Root project>
  3. Cliquer dans le menu de gauche sur “Clean-up rules”
    Cliquez sur “Clean-up rules”
  4. Cliquer sur “Edit” pour affecter des règles valables pour tous les projets,
  5. Affecter des valeurs qui permettront de supprimer périodiquement les fichiers de builds, par exemple:
    Exemple de paramètres “Clean-Up Rules”

En conclusion

Toutes ces étapes ont permis de paramétrer un serveur Teamcity de façon à ce qu’il soit opérationnel pour exécuter des builds. Dans un prochain article, on indiquera quelles sont les fonctionnalités principales de Teamcity pour paramétrer rapidement une configuration de build dans le cadre de .NET.

Leave a Reply