Article
· Déc 11, 2023 10m de lecture

Diffusion continue de votre solution InterSystems à l'aide de GitLab - Partie VII : CD utilisant des conteneurs

Dans cette série d'articles, j'aimerais présenter et discuter de plusieurs approches possibles pour le développement de logiciels avec les technologies d'InterSystems et GitLab. J'aborderai des sujets tels que:

  • Git 101
  • Flux Git (processus de développement)
  • Installation de GitLab
  • Flux de travail GitLab
  • Diffusion continue
  • Installation et configuration de GitLab
  • GitLab CI/CD
  • Pourquoi des conteneurs?
  • Infrastructure de conteneurs
  • CD utilisant des conteneurs

Dans le premier article, nous avons évoqué les notions de base de Git, les raisons pour lesquelles une compréhension approfondie des concepts de Git est importante pour le développement de logiciels modernes et la manière dont Git peut être utilisé pour développer des logiciels.

Dans le deuxième article, nous avons évoqué le flux de travail GitLab - un processus complet du cycle de vie du logiciel ainsi que Diffusion continue.

Dans le troisième article, nous avons évoqué l'installation et la configuration de GitLab et la connexion de vos environnements à GitLab

Dans le quatrième article, nous avons écrit une configuration de CD.

Dans le cinquième article, nous avons parlé des conteneurs et de la manière dont ils peuvent être utilisés (et pour quelles raisons).

Dans le sixème article nous abordons des principaux composants dont vous aurez besoin pour exécuter un pipeline de diffusion continue avec des conteneurs et de la façon dont ils fonctionnent tous ensemble.

Dans cet article, nous allons créer une configuration de diffusion continue décrite dans les articles précédents.

Flux de Travail

Dans notre Diffusion continue, nous allons:

  • Introduire le code dans le référentiel GitLab
  • Construire l' image docker
  • Tester cette image
  • Publier l'image dans notre registre docker
  • Remplacer l'ancien conteneur par la nouvelle version à partir du registre

Ou en format graphique :

Commençons donc!

Build (csonstruction)

D'abord, nous devons construire notre image.

Notre code sera, comme d'habitude, stocké dans le référentiel, la configuration CD - dans gitlab-ci.yml mais en plus (pour renforcer la sécurité) nous stockerons plusieurs fichiers spécifiques au serveur sur un serveur build.

GitLab.xml

Contient le code d'accrochage du CD. Il a été développé dans l' article précédent et disponible sur GitHub. Il s'agit d'une petite bibliothèque permettant de télécharger du code, d'exécuter divers accrochages et de tester le code. Il est préférable d'utiliser les sous-modules git pour inclure ce projet ou quelque chose de similaire dans votre référentiel. Les sous-modules sont meilleurs car il est plus facile de les mettre à jour. Une autre solution est de baliser les versions sur GitLab et de les télécharger à l'aide de la commande ADD.

iris.key

Clé de licence. Elle peut également être téléchargée lors du conteneur build au lieu d'être stockée sur un serveur. Il n'est pas très sûr de la stocker dans le référentiel.

pwd.txt

Fichier contenant le mot de passe par défaut. Là encore, il n'est pas très sûr de le stocker dans le référentiel. De plus, si vous hébergez l'environnement de production (prod) sur un serveur séparé, il pourrait avoir un mot de passe par défaut différent.

load_ci.script

Script initial qui:

  • Active l'authentification OS
  • Télécharge le fichier GitLab.xml
  • Initialise les paramètres de l'utilitaire GitLab
  • Télécharge le code


set sc = ##Class(Security.System).Get("SYSTEM",.Properties)
write:('sc) $System.Status.GetErrorText(sc)
set AutheEnabled = Properties("AutheEnabled")
set AutheEnabled = $zb(+AutheEnabled,16,7)
set Properties("AutheEnabled") = AutheEnabled
set sc = ##Class(Security.System).Modify("SYSTEM",.Properties)
write:('sc) $System.Status.GetErrorText(sc)
zn "USER"
do ##class(%SYSTEM.OBJ).Load(##class(%File).ManagerDirectory() _ "GitLab.xml","cdk")
do ##class(isc.git.Settings).setSetting("hooks", "MyApp/Hooks/")
do ##class(isc.git.Settings).setSetting("tests", "MyApp/Tests/")
do ##class(isc.git.GitLab).load()
halt

Notez que la première ligne est intentionnellement laissée vide.

Puisque certains paramètres peuvent être spécifiques au serveur, ils ne sont pas stockés dans le référentiel, mais plutôt à part. Si cet accrochage initial est toujours le même, vous pouvez simplement le stocker dans le référentiel.

gitlab-ci.yml

Passons maintenant à la configuration de la diffusion continue :

build image:
  stage: build
  tags:
    - test
  script:
    - cp -r /InterSystems/mount ci
    - cd ci
    - echo 'SuperUser' | cat - pwd.txt load_ci.script > temp.txt
    - mv temp.txt load_ci.script
    - cd ..
    - docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t docker.domain.com/test/docker:$CI_COMMIT_REF_NAME .

Que se passe-t-il ici?

Tout d'abord, comme docker build ne peut accéder qu'aux sous-référentiel d'un référentiel de base build qui est dans notre cas la racine du référentiel, nous devons copier notre référentiel "secret" (celui qui contient GitLab.xml, iris.keypwd.txt and load_ci.script) dans le référentiel cloné.

Ensuite, pour accéder au premier terminal, il faut avoir un utilisateur et un mot de passe, donc il faut les ajouter à load_ci.script (c'est à cela que sert la ligne vide au début de load_ci.script est pour btw).

Enfin, nous construisons l'image docker et la balisons de manière appropriée: docker.domain.com/test/docker:$CI_COMMIT_REF_NAME

$CI_COMMIT_REF_NAME est le nom de la branche courante. Notez que la première partie de la balise de l'image doit être nommée de la même manière que le nom du projet dans GitLab, de manière à ce qu'elle puisse être vue dans l'onglet Registre de GitLab (les instructions sur le balisage sont disponibles dans l'onglet Registre).

Dockerfile

La construction de l'image docker se fait en utilisant Dockerfile, la voici:

FROM docker.intersystems.com/intersystems/iris:2018.1.1.611.0

ENV SRC_DIR=/tmp/src
ENV CI_DIR=$SRC_DIR/ci
ENV CI_PROJECT_DIR=$SRC_DIR

COPY ./ $SRC_DIR

RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/ \
 && cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/ \
 && $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt \
 && iris start $ISC_PACKAGE_INSTANCENAME \
 && irissession $ISC_PACKAGE_INSTANCENAME -U%SYS < $CI_DIR/load_ci.script \
 && iris stop $ISC_PACKAGE_INSTANCENAME quietly

Nous partons du conteneur iris de base.

Tout d'abord, nous copions notre référentiel (ainsi que le référentiel "secret") à l'intérieur du conteneur.

Ensuite, nous copions la clé de licence et le fichier GitLab.xml dans le référentiel mgr.

Ensuite, nous remplaçons le mot de passe par la valeur du fichier pwd.txt. Notez que le fichier pwd.txt est supprimé lors de cette opération.

Ensuite, l'instance est démarrée et le fichier load_ci.script est exécuté.

Finalement, l'instance iris est arrêtée.

Voici le journal de tâches ( incomplet, les journaux de téléchargement/compilation ont été ignorés) :

Running with gitlab-runner 10.6.0 (a3543a27)
  on docker 7b21e0c4
Using Shell executor...
Running on docker...
Fetching changes...
Removing ci/
Removing temp.txt
HEAD is now at 5ef9904 Build load_ci.script
From http://gitlab.eduard.win/test/docker
   5ef9904..9753a8d  master     -> origin/master
Checking out 9753a8db as master...
Skipping Git submodules setup
$ cp -r /InterSystems/mount ci
$ cd ci
$ echo 'SuperUser' | cat - pwd.txt load_ci.script > temp.txt
$ mv temp.txt load_ci.script
$ cd ..
$ docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t docker.eduard.win/test/docker:$CI_COMMIT_REF_NAME .
Sending build context to Docker daemon  401.4kB

Step 1/6 : FROM docker.intersystems.com/intersystems/iris:2018.1.1.611.0
 ---> cd2e53e7f850
Step 2/6 : ENV SRC_DIR=/tmp/src
 ---> Using cache
 ---> 68ba1cb00aff
Step 3/6 : ENV CI_DIR=$SRC_DIR/ci
 ---> Using cache
 ---> 6784c34a9ee6
Step 4/6 : ENV CI_PROJECT_DIR=$SRC_DIR
 ---> Using cache
 ---> 3757fa88a28a
Step 5/6 : COPY ./ $SRC_DIR
 ---> 5515e13741b0
Step 6/6 : RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/  && cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/  && $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt  && iris start $ISC_PACKAGE_INSTANCENAME  && irissession $ISC_PACKAGE_INSTANCENAME -U%SYS < $CI_DIR/load_ci.script  && iris stop $ISC_PACKAGE_INSTANCENAME quietly
 ---> Running in 86526183cf7c
.
Waited 1 seconds for InterSystems IRIS to start
This copy of InterSystems IRIS has been licensed for use exclusively by:
ISC Internal Container Sharding
Copyright (c) 1986-2018 by InterSystems Corporation
Any other use is a violation of your license agreement

%SYS>
1

%SYS>
Using 'iris.cpf' configuration file

This copy of InterSystems IRIS has been licensed for use exclusively by:
ISC Internal Container Sharding
Copyright (c) 1986-2018 by InterSystems Corporation
Any other use is a violation of your license agreement

1 alert(s) during startup. See messages.log for details.
Starting IRIS

Node: 39702b122ab6, Instance: IRIS

Username:
Password:

Load started on 04/06/2018 17:38:21
Loading file /usr/irissys/mgr/GitLab.xml as xml
Load finished successfully.

USER>

USER>

[2018-04-06 17:38:22.017] Running init hooks: before

[2018-04-06 17:38:22.017] Importing hooks dir /tmp/src/MyApp/Hooks/

[2018-04-06 17:38:22.374] Executing hook class: MyApp.Hooks.Global

[2018-04-06 17:38:22.375] Executing hook class: MyApp.Hooks.Local

[2018-04-06 17:38:22.375] Importing dir /tmp/src/

Loading file /tmp/src/MyApp/Tests/TestSuite.cls as udl

Compilation started on 04/06/2018 17:38:22 with qualifiers 'c'
Compilation finished successfully in 0.194s.

Load finished successfully.

[2018-04-06 17:38:22.876] Running init hooks: after

[2018-04-06 17:38:22.878] Executing hook class: MyApp.Hooks.Local

[2018-04-06 17:38:22.921] Executing hook class: MyApp.Hooks.Global
Removing intermediate container 39702b122ab6
 ---> dea6b2123165
[Warning] One or more build-args [CI_PROJECT_DIR] were not consumed
Successfully built dea6b2123165
Successfully tagged docker.domain.com/test/docker:master
Job succeeded

Notez que j'utilise l' GitLab Shell au lieu d'exécuteur Docker. L'exécuteur Docker est utilisé lorsque vous avez besoin de quelque chose de l'intérieur de l'image, par exemple, vous créez une application Android dans un conteneur java et vous n'avez besoin que d'un apk. Dans notre cas, il nous faut un conteneur complet et pour cela nous avons besoin de l'exécuteur Shell. Nous exécutons donc des commandes Docker via l'exécuteur GitLab Shell.

 

Exécution

Nous avons notre image, maintenant nous allons l'exécuter.  Dans le cas de branches de fonctionnalités, nous pouvons juste détruire l'ancien conteneur et démarrer le nouveau. Dans le cas de l'environnement, nous pouvons exécuter un conteneur temporaire et remplacer le conteneur de l'environnement en cas de réussite des tests (c'est un exercice que nous laissons au lecteur).

Voici le script.

destroy old:
  stage: destroy
  tags:
    - test
  script:
    - docker stop iris-$CI_COMMIT_REF_NAME || true
    - docker rm -f iris-$CI_COMMIT_REF_NAME || true

Ce script détruit le conteneur en cours d'exécution et réussit toujours (par défaut, Docker échoue s'il essaie d'arrêter/supprimer un conteneur inexistant).

Ensuite, nous démarrons une nouvelle image et l'enregistrons en tant qu'environnement.Le conteneur Nginx effectue automatiquement le proxy des requêtes en utilisant la variable d'environnement VIRTUAL_HOST et expose une directive (pour savoir quel port sera utilisé pour le proxy).

run image:
  stage: run
  environment:
    name: $CI_COMMIT_REF_NAME
    url: http://$CI_COMMIT_REF_SLUG. docker.domain.com/index.html
  tags:
    - test
  script:
    - docker run -d
      --expose 52773
      --env VIRTUAL_HOST=$CI_COMMIT_REF_SLUG.docker.eduard.win
      --name iris-$CI_COMMIT_REF_NAME
      docker.domain.com/test/docker:$CI_COMMIT_REF_NAME
      --log $ISC_PACKAGE_INSTALLDIR/mgr/messages.log

 

Tests

Faisons quelques tests.

test image:
  stage: test
  tags:
    - test
  script:
    - docker exec iris-$CI_COMMIT_REF_NAME irissession iris -U USER "##class(isc.git.GitLab).test()"

Publication

Finalement, publions notre image dans le registre

publish image:
  stage: publish
  tags:
    - test
  script:
    - docker login docker.domain.com -u dev -p 123
    - docker push docker.domain.com/test/docker:$CI_COMMIT_REF_NAME

L'utilisateur et le mot de passe peuvent être transmis à l'aide des variables secrètes de GitLab.

Maintenant, nous pouvons voir l'image dans GitLab:

Les autres développeurs peuvent l'extraire du registre. Dans l'onglet "Environnements", tous nos environnements sont disponibles pour une navigation simple :

 

Conclusion

Dans cette série d'articles, j'ai abordé les approches générales de la diffusion continue. Il s'agit d'un sujet extrêmement vaste et cette série d'articles doit être considérée plutôt comme une collection de recettes que comme quelque chose de définitif. Si vous souhaitez automatiser la construction, les tests et la diffusion de votre application, la diffusion continue de manière générale et GitLab en particulier sont la manière de procéder. La Diffusion continue et les conteneurs vous permettent de personnaliser votre flux de travail en fonction de vos besoins.

Liens

Prochaine étape

C'est tout ! J'espère avoir couvert les bases de la diffusion continue et des conteneurs.

Il y a un tas de sujets dont je n'ai pas abordé (donc peut-être je ferai ça plus tard), en particulier sur les conteneurs:

  • Les données peuvent être conservées en dehors du conteneur, voici la documentation à ce sujet
  • Plateformes d'orchestration comme kubernetes
  • Gestionnaire "InterSystems Cloud Manager"
  • Gestion de l'environnement - création d'environnements temporaires pour les tests, suppression des environnements obsolètes après la fusion des branches fonctionnelles
  • Docker compose pour les déploiements multi-conteneurs
  • Réduction du poids de l'image docker et des délais de construction
  • ...
Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer