web-dev-qa-db-fra.com

Utiliser Git pour déployer une mauvaise pratique?

J'ai tendance à utiliser Git pour déployer le code de production sur le serveur Web. Cela signifie généralement que quelque part un référentiel Git maître est hébergé quelque part accessible sur ssh, et le serveur de production sert ce référentiel cloné, tout en restreignant l'accès à .git/ et .gitignore. Lorsque j'ai besoin de le mettre à jour, je tire simplement vers le référentiel du serveur depuis le référentiel maître. Cela présente plusieurs avantages:

  1. Si quelque chose se passe mal, il est extrêmement facile de revenir à une révision antérieure - aussi simple que de l'extraire.
  2. Si l'un des fichiers de code source est modifié, vérifiez-le aussi facilement que git status, et si le dépôt du serveur a été modifié, cela deviendra évident la prochaine fois que j'essaierai de tirer.
  3. Cela signifie qu'il existe une copie de plus du code source, au cas où de mauvaises choses se produisent.
  4. La mise à jour et la restauration sont faciles et très rapides.

Cela pourrait cependant poser quelques problèmes:

  • Si, pour une raison quelconque, le serveur Web décide qu'il doit servir .git/ répertoire, tout le code source qui existait et est lisible par tout le monde. Historiquement, certaines (grandes) entreprises ont fait cette erreur. J'utilise .htaccess fichier pour restreindre l'accès, donc je ne pense pas qu'il y ait de danger pour le moment. Peut-être un test d'intégration garantissant que personne ne peut lire le .git/ le dossier est en ordre?

  • Toute personne qui accède accidentellement en lecture au dossier a également accès à toutes les révisions passées du code source qui existaient auparavant. Mais cela ne devrait pas être bien pire que d'avoir accès à la version actuelle. Après tout, ces révisions sont par définition obsolètes.

Cela dit, je pense que l'utilisation de Git pour déployer du code en production est raisonnablement sûre et beaucoup plus facile que rsync, ftp, ou simplement la copier. Qu'est-ce que tu penses?

109
Septagram

J'irais jusqu'à envisager d'utiliser git pour le déploiement très bonne pratique .

Les deux problèmes que vous avez répertoriés ont très peu à voir avec l'utilisation de git pour le déploiement lui-même. Remplacer .git/ pour le fichier de configuration contenant les mots de passe de la base de données et vous rencontrez le même problème. Si j'ai un accès en lecture à votre racine Web, j'ai un accès en lecture à tout ce qu'il contient. Il s'agit d'un problème de durcissement du serveur dont vous devez discuter avec votre administration système.

git offre des avantages très intéressants en matière de sécurité.

  1. Vous pouvez appliquer un système pour le déploiement en production. Je configurerais même un post-receive hook à déployer automatiquement en production chaque fois qu'un commit sur master est effectué. Je suppose bien sûr, un flux de travail similaire à git flow .

  2. git facilite extrêmement la restauration du code déployé en production vers une version précédente en cas de problème de sécurité. Cela peut être utile pour bloquer l'accès aux failles de sécurité critiques que vous avez besoin de temps pour corriger correctement.

  3. Vous pouvez appliquer un système où vos développeurs doivent signer les commits qu'ils font. Cela peut aider à déterminer qui a déployé quoi en production si une faille de sécurité délibérée est détectée.

77
user10211

Il n'y a rien de mal à déployer à partir d'un dépôt git, en fait, c'est une pratique assez courante et, comme vous le dites, beaucoup moins sujet aux erreurs que la copie de fichiers via ftp ou rsync.

Compte tenu des informations que vous avez fournies, je noterais les points suivants:

  • Ne vous contentez pas de tirer sur le dernier maître. La production doit être déployée à partir d'une balise de version. Utilisez git flow ou similaire pour obtenir un peu plus de processus autour du déploiement du code et de la création des balises. Parce que les balises sont une référence immuable à votre code à un moment donné, c'est plus stable que de pointer vers une branche principale qui pourrait être mise à jour par un commit errant.

  • Quant à servir le répertoire .git, cela ne devrait pas être un gros problème. Il suffit de rediriger tout ce qui est préfixé avec .git vers un 404 in .htaccess.

  • Votre authentification git doit être basée sur la clé ssh, donc aucun mot de passe repo ne doit être stocké sur le serveur.

Vive les workflows de déploiement git!

26
Matt Surabian

Vous pouvez utiliser le --separate-git-dir=<git dir> argument lors de l'appel git clone . Cela placera un lien symbolique dans le .git répertoire (symbolique pour Git, je ne pense pas que ce soit un lien symbolique vers votre système d'exploitation), et vous pouvez spécifier le <git dir> quelque part en dehors de la racine du document.

8
Brendon

Je vais être en désaccord avec l'opinion populaire ici. Git est pour le contrôle de version, ce n'est pas pour le déploiement/CI.

Les méthodes préconisées ici conviennent parfaitement aux petits projets, mais de manière générale, elles ne sont pas très efficaces.

... ce qui ne veut pas dire que vous ne devez pas continuer à faire ce que vous faites. Gardez à l'esprit, au cours de votre carrière, que les projets sur lesquels vous travaillez vont probablement dépasser un flux de travail de déploiement purement basé sur Git.

Le principal changement de paradigme consiste à arrêter de penser au déploiement de branches, à commencer à penser au déploiement des résultats de la construction et à injecter des dépendances d'environnement pour dissocier votre infrastructure de votre stratégie de branche.

Par exemple, pour utiliser le paradigme ci-dessus sur le "déploiement de fichiers" et la restauration. Si vous étiez en train de déployer des fichiers, vous pouvez conserver plusieurs versions de l'application sur le serveur de production, et si vous devez revenir en arrière, vous pouvez pointer votre serveur Web vers une version plus ancienne en reliant à nouveau la racine Web. Deux commandes Shell, microsecondes de temps d'arrêt, moins de marge d'erreur que d'utiliser git.

Un autre exemple - vous avez la branche de développement standard> branche de transfert> flux de travail maître, avec un serveur pour chacun. Vous avez des trucs prêts à aller dans le développement, mais d'autres trucs sur la mise en scène ont échoué le contrôle qualité. Vous devez donc effectuer certaines opérations laides - supprimer les mauvaises validations de la phase, redéployer la phase, et également supprimer ou corriger les mauvaises validations en cours de développement, et espérons que le développement et la mise en scène ne finissent pas par être désynchronisés.

Au lieu de cela, que se passe-t-il si vous coupez une branche de publication hors du maître, fusionnez les éléments prêts à entrer dans cette branche de version et construisez le résultat, faites tourner un serveur de test sur AWS et déployez le résultat sur celui-ci, exécutez votre QA et vos tests fonctionnels contre ce serveur temporaire de transfert, puis a poussé ce même résultat vers le cluster de production et l'a déployé? Désactivez ensuite la zone de transfert temporaire que vous avez créée, fusionnez la version en maître et étiquetez le maître avec un numéro de version.

De toute évidence, ce sont des exemples extrêmes. Habituellement, ce n'est pas si propre, même si nous voulons que ce soit le cas - vous devez probablement exécuter certains processus de génération dans l'environnement cible, car vous devez modifier la base de données. Et si vous avez des mods de base de données non idempotents entre les versions, eh bien, la restauration ne sera pas aussi simple, quelle que soit la méthode que vous utilisez, car vous devrez restaurer la base de données (en général, essayez de déployer la base de données idempotente modifications, puis supprimez les bits de base de données obsolètes dans une version ultérieure, une fois que vous êtes sûr qu'ils sont hors du flux d'application).

Quoi qu'il en soit, je suppose que je veux en venir, est-ce que ma réponse à `` Est-ce que l'utilisation de git pour le déploiement est une mauvaise pratique? '' est, d'une manière générale, "Oui", de la même manière que l'utilisation de roues d'entraînement est mauvaise pour le vélo. C'est une amélioration par rapport à la casse répétée de votre cul sur le béton, mais vous l'espérez, vous finirez par le dépasser.

8
siliconrockstar

Une approche alternative que j'ai adoptée auparavant est quelque chose de similaire au commentaire de Terry Chia concernant les hooks post-réception.

Git a n certain nombre de crochets qui peut être utilisé pour effectuer toutes sortes de tâches avant/pendant/après plusieurs actions différentes.

Créez un référentiel nu ailleurs que dans votre dossier Web. Le référentiel nu peut alors être utilisé comme distant pour pousser vers , et un hook post-réception peut être déclenché pour extraire le nouveau code dans un répertoire spécifié.

Cette approche présente certains avantages: l'emplacement de déploiement agit comme une rue "à sens unique" où le code doit passer par le contrôle de code source pour finir en production. Vous pouvez déployer différentes branches/versions à différents emplacements (tous à partir du même référentiel nu). Il fournit également un moyen facile et agréable de revenir en arrière en utilisant la vérification Git standard. Cependant, une mise en garde/conséquence de ceci est que les modifications de code sur le serveur ne se refléteront pas dans git (les référentiels nus n'ont pas de répertoires de travail), vous devrez donc effectuer manuellement git --work-tree=/path/to/code status pour voir les changements (mais vous ne devriez pas changer le code de production de toute façon, non?)

5
russdot

Je suis d'accord avec Terry Chia que c'est une très bonne pratique. Il assure:

  • que la révision en place est la bonne,
  • avec tous les fichiers nécessaires et vérifie l'exhaustivité de la version,
  • rendre la procédure de déploiement rapide et facile

Mais je dois ajouter qu'il y a des mises en garde que j'ai envie de partager.

Habituellement, dans un référentiel git, vous mettez:

  • code,
  • docs,
  • tests unitaires,
  • scripts de déploiement,
  • outils d'intégration,
  • archives .deb,
  • patchs SQL
  • ou des trucs comme ça, et peut-être un tas d'autres trucs

Eh bien, en production, vous voulez juste le code!

Parce que les documents, les tests unitaires, les outils ou les archives .deb peuvent prendre beaucoup d'espace disque et n'ont rien à voir en production.

Avec Subversion (avant la version 1.7), vous pouviez commander uniquement le src/ répertoire et vous avez tous les avantages. Mais avec Subversion> 1.7 et avec Git, vous ne pouvez pas faire ça.

Une alternative serait d'utiliser des sous-modules git pour réaliser ce type d'architecture: project repo |- doc |- src -> submodule to project-src repo. \ tests Mais alors votre projet/tests et votre code de projet-src ne seraient pas synchronisés et cela serait vraiment nul.

La solution consisterait alors à utiliser la "caisse clairsemée", voir: https://stackoverflow.com/questions/600079/how-do-i-clone-a-subdirectory-only-of-a-git- référentiel

Vous pouvez donc utiliser git, mais veuillez faire attention à ces inconvénients.

3
Thibault

Voici le script que j'utilise pour faire git to Push to prod.

https://Gist.github.com/Zamicol/f160d05dd22c9eb25031

Il suppose que tout ce qui est poussé vers la branche principale est prêt pour la production. Toutes les autres branches poussées sont ignorées. Vous pouvez modifier ce script de crochet en fonction de vos besoins.

En ce qui vous concerne, je place mon répertoire git sous/var/git et mes fichiers de production ailleurs (comme/var/www) et restreins l'accès à ces répertoires.

Vous pouvez également avoir votre dépôt git sur un serveur distinct de votre serveur de production, puis utiliser quelque chose comme scp et ssh dans le script ci-dessus pour déplacer vos fichiers du serveur git vers le serveur de production. Cela vous permettrait d'utiliser toujours git to Push pour produire tout en gardant votre code séparé de votre production.

1
Zamicol