Le packaging sous Linux
Le packaging est souvent une opération sous-estimée. Pourtant il s’agit de la manière dont vous aller diffuser votre application à votre ou vos clients. Le packaging ne sert qu’a une chose, faciliter le déploiement de votre application sur vos postes cibles. Dans le cadre des clients lourds, ont est souvent bien équipés, MSI, Wizards en tout genre etc… mais nos pauvres applications en PHP, Java destinées à être installées sur des serveurs sont oubliées. En fait, c’est même un phénomène étrange. Certains préfère à chaque projet réinventer la roue, réécrire des procédures complexes, plus ou moins automatiser le packaging et enfin perdre du temps systématiquement. Alors STOP. A tout ceux qui ne font pas de packages industrialisés, prenez le temps de lire cet article. J’espère vous convaincre de changer de méthode. Exit les zip, tar.gz et autre archive… place aux RPM et DEB.
Principe
Le principe des packages “industriels” est de fournir une procédure de déploiement automatisée et de vérifier les dépendances. Ce type de packaging se résume selon moi (pour les serveurs Linux) aux RPM et DEB, utilisables avec des systèmes comme yum (pour RPM) et aptitude ou dpkg (pour DEB). En PHP, il existe un système dédié appelé PEAR. C’est utile mais pas dans le cadre du déploiement d’une application spécifique. Un package Linux (RPM ou un DEB) va donc vérifier que les dépendances nécessaires à votre projet (JRE, PHP, Apache ou autre) est bien installé avant de lancer l’installation. Ce genre de package sait installer, désinstaller, nettoyer les fichiers, sauvegarder les fichiers de configuration, monter et descendre de version et j’en passe. Dans le monde Linux, la création de ces packages est considéré comme un projet à part entière. Les packages sont donc versionnés et suivi par un “release manager”. On prends les sources de l’application (anciennement votre zip ou tar.gz) pour l’ajouter à un système de déploiement complet.
Mise en oeuvre
Bizarrement je ne vais pas parler des packages DEB dans cet article. La raison est qu’il est facile de convertir efficacement un RPM et DEB et donc de couvrir presque la totalité du parc de serveurs Linux. Si l’on sait faire un RPM, on pourra donc le déployer sur la plupart des distributions Linux. Lançons nous dans la création de notre RPM.
Pré-requis
Pour constituer un package, il nous faut plusieurs “input” : les sources/fichiers a déployer, ils sont contenus dans vos actuelles archives, et un fichier de description du package. Il nous faut aussi un environnement adéquat. Personnellement, je test la création de mes packages sous une VM Ubuntu (oui, même pour faire du RPM). Cette VM permet de flinguer un environnement si l’on se plante sans perdre de données (sauvegarder la avant…). Les packages indispensables sont :
1 |
rpm-build make gcc rpmdevtools |
et
1 |
alien |
si vous voulez convertir un RPM en DEB.
Structure
La première phase c’est de préparer votre environnement de travail. Créer vos un dossier “package” dans votre “home” histoire de retrouver vos petits. Ensuite, créer l’arborescence standard RPM :
1 2 3 |
cd ~ mkdir -p rpm mkdir -p rpm/{BUILD,RPMS,SOURCES,SPECS,SRPMS,tmp} |
Les dossiers vont contenir :
- rpm/BUILDS : L’espace de travail durant la compilation du package.
- rpm/RPMS : Le package résultant
- rpm/SOURCES : Les sources décompressées de votre application
- rpm/SPECS : Le fichier de description du package
- rpm/SRPMS : Le package résultant (s’il est signé)
- rpm/tmp : Les fichiers temporaires créés durant la compilation du package.
Ensuite, il est préférable de renseigner les variables “macros” pour le rpm dans un fichier “.rpmmacros” :
1 2 3 4 |
touch ~/.rpmmacros echo "%packager VOTRE NOM" > ~/.rpmmacros echo "%_topdir ~/rpm" >> ~/.rpmmacros echo "%_tmppath ~/rpm/tmp" >> ~/.rpmmacros |
Nous voilà prêt, au boulot maintenant.
Remarques :Pour la suite, on va parler avec des variables :
1 2 3 4 5 |
SOURCES="/emplacement/de/mon/archive/projet/monprojet-1.0.0.tar.gz" VERSION="1.0.0" RELEASE="1" RPMDIR="~/rpm" PKGNAME="monprojet" |
Etape par étape
1. Copier l’archive (contenant les fichiers/sources) de votre application dans le dossier “$RPMDIR/SOURCES”
1 |
cp $SOURCES $RPMDIR/SOURCES/$PKGNAME-$VERSION.tar.gz |
2. Créer ensuite votre fichier de description. Le nom est important, dans notre cas :
1 |
touch $RPMDIR/SPECS/$PKGNAME.spec |
3. Renseigner le fichier de description :
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 41 42 43 44 45 46 47 48 49 50 51 52 |
Name: $PKGNAME Summary: Résumé de votre application Version: $VERSION Release: $RELEASE License: à définir Group: à définir Source0: $PKGNAME-%VERSION%.tar.gz BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot BuildRequires: liste des packages requis pour la compilation Requires: liste des packages requis pour l'installation Prefix: /var/www %description Description (max 79 caractères par ligne) # Préparation du package %prep %setup -q # Compilation du logiciel (execute ./configure et make) %build # Installation de l'application (execute make install) %install echo "Installation" rm -rf $RPM_BUILD_ROOT/%{prefix}/$PKGNAME mkdir -p $RPM_BUILD_ROOT/%{prefix}/$PKGNAME cd $RPM_BUILD_ROOT/%{prefix}/$PKGNAME # TODO : Ici il faut peut être limiter les fichiers à copier si votre archive d'origine n'est pas propre cp $RPM_BUILD_DIR/%{name}-%{version}/* $RPM_BUILD_ROOT/%{prefix}/$PKGNAME -r install -m 0755 -d $RPM_BUILD_ROOT/%{prefix}/$PKGNAME # Nettoyage du package %clean rm -rf $RPM_BUILD_ROOT # Pre installation %pre # TODO : Création des utilisateurs, des groupes etc... # Post installation %post # TODO : Test installation ? # TODO : Ajout des scripts en crontab # Pré désinstallation %preun # TODO : Backup database, configuration files etc... # Post désinstallation %postun # TODO : Suppression utilisateur etc... # Fichier embarqués %files %defattr(-,root,root,-) %{prefix}/$PKGNAME # TODO : Affiner le placement des fichiers %changelog * Mon Sep 09 2013 PRENOM NOM (monadresse@email.com) - Initial packaging version |
C’est ce fichier qui est le plus important. Prenez le temps de regarder les TODO. Les différentes directives “%” sont amplement décrite dans les sites officiels RPM. L’idée étant que :
- %description : Décrit l’application
- %prep : Prépare le packaging
- %build : Construit le package
- %clean : Nettoyage de la construction du package
- %install : Installation dans le package
- %pre : Pré installation de l’application
- %post : Post installation de l’application
- %preun : Pré désinstallation de l’application
- %postun : Post désinstallation de l’application
- %files : Liste des fichiers à copier lors de l’installation
- %changelog : Liste des changements sur le package
4. Et maintenant, compilons !
1 |
rpmbuild -ba $RPMDIR/SPECS/$PKGNAME.spec -v |
En sortie vous allez avoir un jolie package RPM. Si vous avez décider de convertir ce package en DEB :
1 |
alien -k --scripts $RPMDIR/RPMS/noarch/$PKGNAME-$VERSION-$RELEASE.noarch.rpm |
En sortie, vous avez donc un .deb et un .rpm. Vous pouvez installer ça sur votre distribution préférée.
1 |
dpkg --install monprojet_1.0.0-1_all.deb |
ou
1 |
rpm -ivh monprojet_1.0.0-1_all.rpm |
Aller plus loin, le dépôt
Dans un prochain article, on verra comment mettre un place un dépôt. C’est le must dans vous distribuez votre package. Votre client ajoutera ce repository à la liste de ses repository ce qui lui permettra de faire des updates en une ligne…
Conclusion
La mise en place des packages c’est compliqué la première fois, la seconde fois aussi. Mais avec un peu de réflexion, on arrive à un résultat très satisfaisant et surtout très “pro”. Vu que c’est la première impression de votre client pensez y.