Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Première dockerization #32

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open

Première dockerization #32

wants to merge 44 commits into from

Conversation

bugeaud
Copy link

@bugeaud bugeaud commented Jun 11, 2018

Cette branche effectue une dockerisation.

3 conteneurs sont créés :

  • web : pour le frontal web via Ubuntu 18.04 & Apache
  • db : pour le stockage via Mariadb
  • myadmin : pour faciliter l'administration de la base

Un fichier config.yml par défaut est créé. Ceci court-circuite de de fait certaines phases de l'installation classique.

Le README a été mis à jour pour détailler l'installation via Docker.

Hormis la modification de quelques fichiers de configuration (identifiant base, mot de passe base, hachés et nom d'hôte), la procédure est automatique.

Un problème connu a été identifié : lors du premier "docker-compose up", un répertoire de log pour apache2 n'est pas créé automatiquement. La procédure de contournement est documentée (création du répertoire et relancement du "up").

@MedShake
Copy link
Owner

Merci pour ce gros boulot ! Il me reste à tester tout cela.
Quelle est la meilleure stratégie pour intégrer ce pull request ?
J'ai pensé créer une branche "master-docker" dédiée, mais j'en suis encore à la découverte du travail collaboratif ... !

B.

@bugeaud
Copy link
Author

bugeaud commented Jun 12, 2018

De façon générale, si les modifs du pull request n'induisent pas de régressions dans le master, l'inclusion dans le master est de mise = principe KISS.

Pour le cas particulier de ce PR, le seul impact réel du commit est la création d'un fichier config par défaut qui court-circuite la partie de procédure d'install visant à construire une config et à initialiser la base. Ces parties sont maintenant prises en charge par docker. Il ne reste plus dans l'install d'origine que la partie initialisation applicative d'utilisée (actuellement réduite à créer un premier utilisateur applicatif).

Vue la simplicité et l'efficacité d'une dockerisation, la procédure ainsi remplacée s'en trouvé dépréciée de fait. On peut même se poser la question de sa suppression à moyen terme si aucun cas d'usage ne la justifiant se présente. Car il n'est jamais trés bon d'avoir du code d'install méllangé au code applicatif, surtout s'il est ancien ou peu utilisé.

En complément, l'approche dockerisée permet de documenter clairement les étapes nécessaire à l'installation de EHR pour permettre une personalisation de la procédure (modification ou dérivation).

Ceci est démontré dans la dockerisation du module GynObs qui a été facile et rapide. Le même processus peut être appliqué à tous les mods actuels ou à venir.

En synthèse :

  • Tester et recetter
  • Si ok, injecter dans le master

Cdt,
JB

@MedShake
Copy link
Owner

Bon, j'ai peur que cela ne soit pas aussi simple :-)
D'abord parce qu'aucun des contributeurs initiaux n'a d'expérience dans la situation proposée et qu'il va falloir qu'on pèse les tenants et les aboutissants et que l'on comprenne comment cela fonctionne. Après une grosse année de travail et une situation à peine stabilisée avec la 4.0.0 et son LAP, il est difficile de remettre tout sur la table et de plonger dans un nouvel inconnu.
Il faut aussi savoir quoi proposer aux utilisateurs actuels en termes d'upgrade futur et à ce propos, je vois déjà un problème énorme : la mise à jour comme l'installe de nouveaux modules passe par le drag and drop d'un zip dans le navigateur. Si dans les sources nous avons un config.yml, au prochain drag and drop,celui de l'utilisateur va dégager ... bye bye la config ... :D
De même l'intérêt de la dockerisation des modules est difficilement compréhensible et parait largement plus complexe que le drag an drop.
Bref, il se trouve que nous sommes sur l'irc freenode canal medshakeehr et que ça serait parfait pour entamer la discussion (pour ne pas dire formation !) sur tout ça !
Merci !

B.

@bugeaud
Copy link
Author

bugeaud commented Jul 23, 2018

J'ai mis à jour la branche bugeaud/MedShakeEHR-base afin qu'il soit compatible avec le principe actuel de chargement de la configuration.

En complément d'un ensemble de docker compose, on a également une version "docker-in-docker" qui propose un conteneur unique (cf. scriptes "single") ainsi qu'un Dockerfile par défaut. Ceci va nous permettre d'instancier des Medshake EHR à la volée/demande via les services cloud.

Le README est mis à jour en conséquence.

Le principe général : un système de substitution de variables effectue le remplacement automatique (lors de la phase de config) des fichiers identifié par un suffixe +envsubst. Il crée ainsi des fichiers de configuration "legacy" sur la base des variables d'environement EHR_* correspondant aux différents besoins. Ceci permet de conteneriser sans toucher à l'existant.

Bon tests

@MedShake
Copy link
Owner

Bonjour
Merci pour tout ce boulot.
Comme dit, aucune expérience de la chose.
Un mots de procédure pour mettre en oeuvre le tout (sous linux) et tester de façon correcte sans faire n'importe quoi ? :D
Merci !

B.

@bugeaud
Copy link
Author

bugeaud commented Jul 25, 2018

Bonjour Bertrand,

RTFM ;-)
https://github.com/MedShake/MedShakeEHR-base/blob/master/README.md
Je viens de refaire une passe dessus. N'hésites pas à faire des retours.

Focalises dans un premier temps la conf Docker, et laisse de coté la Docker-in-Docker.
PI, cette dernière va nous permettre d'avoir des machines EHR à la demande. J'ai encore quelque points d'intégration à voir avec les services le permettant (principalement un problème de nom de machine et de génération de certificat par certbot)

Je pense qu'il serait interessant de faire un point audio pour vous présenter tout ceci de vive voix dans les jours/semaines à venir.

++
JB

@MedShake
Copy link
Owner

Salut
J'essaye, j'essaye mais ...
A l'étape 5 : "/docker-ehr-config.sh: 33: eval: Bad substitution"
Je n'ai défini que la variable d'env obligatoire.

B.

@bugeaud
Copy link
Author

bugeaud commented Jul 30, 2018

Oups, j'ai utilisé un type expression qui n'est effectivement pas disponible sur tout les shells.

Pour contourner temporairement et continuer ton test, tu peux modifier la 1e ligne :
#!/bin/sh
en :
#!/bin/bash

Je ferais des tests pour voir si je peux faire un plus simple eval à la place qui marche sur un maximum de shells. Dans le cas contraire, je ferais un commit avec le forçage à bash pour l'instant sur les scripts.

Dis-moi si tu vois d'autres soucis ...

++
JB

@bugeaud
Copy link
Author

bugeaud commented Jul 30, 2018

J'ai fait un commit pour corriger ce point. Pour l'instant j'ai laissé Bash en requis. Si celà pose un soucis, le scripte pourra être repris plus tard car il y a peu d'adhérence avec le reste de la dockerisation.

@MedShake
Copy link
Owner

De nouveau bloqué :

./docker-ehr-prepare.sh
DONE File structure checked
cat: '/var/lib/dhcp/dhclient*.leases': Aucun fichier ou dossier de ce type

Et pas de retour du prompt.

B.

@bugeaud
Copy link
Author

bugeaud commented Jul 31, 2018

Grr. Effectivement, si la config n'a pas de dhclient, le test ne peut pas passer. Par contre l'absence d'invite est surprenante ...

J'ai corrigé le test dans mon master. Sachant que je n'ai pas vu de solution portable pour obtenir le premier dhcp de résolution ... ceux qui ne seront pas en dhclient n'auront pas de contournement automatique du problème de EAI_RETRY pour l'instant. Pour info, ce problème apparait sur certains hébergement qui ont une limitation de la bande passante vers les DNS public de posé au niveau des hébergeurs.

++
JB

@MedShake
Copy link
Owner

MedShake commented Aug 3, 2018

Un peu chinois pour moi la réponse. Mon test est fait sur une mint 19. Je vais essayer de comprendre ce qui manque. (Je serais un peu moins réactif ce mois d’août concernant l'EHR car je dois upgrader medshake.net) .

B.

@bugeaud
Copy link
Author

bugeaud commented Aug 3, 2018

Re,
Dhclient est un client utilisé pour récupérer les adresses IP sur une machine linux (un serveur ici) via DHCP. Soit la Mint 19 n'utilise pas dhclient (à vérifier) soit les chemins ne sont pas les mêmes. J'ai pour l'instant courcircuité la fonctionalité de DNS local forcé dans Docker. Car cette fonctionalité nécessite d'analyser la conf DHCP et je ne l'ai faite que pour utiliser celle de dhclient pour l'instant.
Le DNS local forcé est nécessaire dans certains cas car par défaut Docker utilise les DNS publics et non ceux dérivés du fournisseur d'hébergement. Mais certains fournisseurs ont une limite sur la bande passante allouée au DNS public : ils préférent que leurs clients privilégient les DNS locaux car ils ont un coût de fonctionnement plus restreint ( serveur + bande passante locale vs bande passante longue distance). Cette préférence fait que sur certains hébergeur (Scaleway par exemple) on a des erreurs de résolution DNS (aucune réponse à temps) et donc de connexion (pas d'IP correspondant à un nom = pas de connexion). Le symptome est souvent dans le cas de EHR des messages d'erreur de type EAI_RETRY sans justification (le DNS et le site est bien là ... mais l'erreur dit le contraire).

Si tu lance cette appli docker sur une serveur maison ou chez un hébergeur qui n'a pas cette contrainte, le forçage du DNS local n'est pas un pré-requis.

@bugeaud
Copy link
Author

bugeaud commented Dec 21, 2022

Je l'ai pourtant de opérationel sur 2 environements : 1 env dev Jammy/docker direct et prod 1 env jammy/lxc/docker depuis plusieurs années. Il peut toujours y avoir un delta mais je ve vois pas lequel. L'avez-vous testé aussi sans virt pour confirmer que c'est KO sur debian bare aussi ?

@marsante
Copy link
Contributor

Je n'ai pas de machine physique à réinstaller sans données sensibles actuellement donc je ne pourrai pas. J'avais testé il y a 2-3 ans sans aboutir sur une machine physique, mais je ne me rappelle plus si c'était le même problème.

Je peux à la rigueur tester sur une VM VirtualBox, et un conteneur LXC, mais j'ai retesté d'autre projet sur la VM et
les docker-compose d'Apache, PHP, Nextcloud, WordPress et mon docker-compose de MedShakeEHR fonctionnent, alors a priori ma VM fonctionne bien. Il m'est arrivé probablement plus d'une fois sur un projet de faire des petites modifs en oubliant de les répercuter dans les scripts ou documentation ce qui fait que je ne voyais pas le problème pour les autres 😅.
Avez-vous retesté votre projet sur un environnement neuf récemment ? Je vous tiens au courant quand j'aurai créé ma VM VirtualBox et mon container LXC si j'ai abouti.

@marsante
Copy link
Contributor

J'ai avancé sur les tests : Ubuntu desktop live CD ça marche et j'aboutis. Debian 11 netinstall (avec environnement Gnome 3) ça marche et j'aboutis. Dans les deux les scripts du DNS s'exécutent bien avec le message final as your DHCP configuration is currently not supported by this script. If Docker generate some DNS issues EAI_RETRY, please open an issue with details of your distribution & environment."
Ensuite, j'ai testé l'installation de la VM qui posait un problème, Debian 11 via le live cd Debian gnome. Là le script du DNS plante et boucle à l'infini. Est-ce que c'est parce que sur ce type d'installation le fichier dhclient*.leases est présent, mais vide alors que sur les deux autres installations, il est absent. Je n'ai pas encore creusé. En commentant les lignes du script du DNS, j'ai pu continuer l'installation et là ça marche.
Retour sur la VM défectueuse désinstallation de docker du repos GitHub et des traces de fichiers installés. Relance de la procédure, ça plante au niveau des DNS comme celle du dessus. Désactivation du script DNS, l'installation se passe bien, mais toujours pas de communication dans le navigateur. Finalement en regardant l'affichage sur les autres VM, j'ai compris que la redirection HTTPS ne venait pas de ce conteneur, mais probablement du mien. Teste en navigation privée, ça marche 😆 Problème de cache. Reste le mystère de pourquoi à part le mien, les autres conteneurs fonctionnaient.
Je vais enfin pouvoir tester la suite. L'occasion de reconfirmer le bug des croix des tâches cron non prisent en compte sur la page dédiée.

@marsante
Copy link
Contributor

marsante commented Mar 2, 2023

Je retrouve un peu de temps pour pouvoir contribuer.
Hier, j'ai repris l'organisation de l'image docker de wordpress. La mise en place de medshakeehr se fait via un entrypoint. Ce qui permet de passer des parties de medshakeehr en volume, ou en entier et dans ce cas-là, de le gérer comme sur une installation classique. Pour le moment seuls les volumes dockers marchent, j'ai dû louper quelque chose sur la gestion des droits. C'est dispo ici avec les instructions d'installation https://hub.docker.com/r/marsante/msehrtest. Autre avantage, il n'y a plus besoin de modifier le dépôt principal pour se plier à docker.

@marsante
Copy link
Contributor

marsante commented Mar 2, 2023

j'ai corrigé le souci de volume et j'ai mis à jour l'image en 7.3

@bugeaud
Copy link
Author

bugeaud commented Mar 3, 2023

Le problème de EHR est la nécessité de modifier le fichier de config positionné pour avoir un lancement initial pour la partie web en gardant un entrypoint le plus simple/basique possible. Car les JSON contrairement aux .conf d'Apache HTTP ne permettent pas de directement récupérer les valeurs d'une variable d'env. Au minimum il faut utilisateur et mdp vers la base et idéalement le nom du serveur/vh. Sachant que le reste des paramètres sont ensuite récupérés en base. J'ai testé une approche par surcharge par ENV des fichiers de config sur API-CCAM-NGAP dans le cadre de l'automatisation car elle est similaire dans son fonctionnement à EHR (voir https://github.com/bugeaud/API-CCAM-NGAP/blob/master/public_html/index.php#L49-55 ) et nécessaire en plus à EHR pour les tarifs automatiques. A date, l'automatisation fonctionne déjà sur la partie CCAM via un simple docker-compose up et des deux images sur dockerhub (web et db).

Il me reste à automatiser la partie NGAP et documenter le tout. Ensuite je reviendrais sur ce PR d'EHR pour faire une intégration similaire mais avec un préfixe spécifique de variable type "EHR_" et supprimer les scripts qui seront devenues obsolètes.

On aura ainsi un ensemble propre et automatisé : EHR, API, ORTHANC

Un peu comme Orthanc, je pense qu'il nous faut anticiper plusieurs images pour EHR, une "all" avec un maximum de mods ajoutés lors du BUILD et des variantes par spécialités avec base et le mod de la spécialité pour ceux qui veulent optimiser leur stockage.

@marsante
Copy link
Contributor

marsante commented Mar 6, 2023

Pour l'entrypoint j'ai fait comme ça pour passer les variables :

#!/bin/bash
set -e

if [ ! -e /var/www/html/public_html/index.php ]; then
    echo "Copie de MedShakeEHR ..."
    cp -pr /usr/src/medshakeehr/* /var/www/html/
    cd /var/www/html && \
    composer install -n --no-plugins --no-scripts --no-cache --no-ansi --no-progress --no-dev -o && \
    cd public_html && \
    composer install -n --no-plugins --no-scripts --no-cache --no-ansi --no-progress --no-dev -o
fi

if [ ! -e /var/www/html/config/config.yml ]; then
    echo "Configuration absente, création ..."
    echo "
sqlRootId: ""
sqlRootPwd: ""
sqlNotCreatDb: true
protocol: $PROTO://
host: $VIRTUAL_HOST
port: $PORT
urlHostSuffixe: ""
webDirectory: /var/www/html/public_html/
stockageLocation: /var/www/html/stockage/
backupLocation: /var/www/html/backups/
workingDirectory: /var/www/html/public_html/workingDirectory/
cookieDomain: $VIRTUAL_HOST
cookieDuration: $COOKIED
fingerprint: $FINGERPRINT
sqlServeur: db
sqlBase: $MYSQL_DATABASE
sqlUser: $MYSQL_USER
sqlPass: $MYSQL_PASSWORD
sqlVarPassword: $SQLVARPSWD
templatesFolder: /var/www/html/templates/
twigEnvironnementCache: false
twigEnvironnementAutoescape: false
twigDebug: false
configForm: ""
        " > /var/www/html/config/config.yml
fi

uid="$(id -u)"
if [ "$uid" = 0 ]; then
    chown -R www-data:www-data /var/www/html/
fi
exec "$@"

@MedShake
Copy link
Owner

MedShake commented Mar 7, 2023

Bon, comme vous avez vu, j'ai lavé mon cerveau ces derniers jours en faisant pas mal de choses sur le code PHP.
C'est amusant car je n'avais pas vu la discussion, mais j'ai passé mon insomnie de la nuit dernière sur le sujet en me disant : "il faudra qu'ils m'expliquent vers quoi il faut aller vraiment pour que ca puisse passer en docker".
Il faudra être simplex et me parler le moins possible de Docker : parlez-moi de l'app, de sa problématique multimodule, de sa config. S'il faut revenir à du yaml dans /config, c'est pas compliqué, c'est ce que j'ai toujours voulu faire :-) mais mon coéquipier des débuts a poussé pour une mise en base et surtout une interface graphique de gestion.
Bref, dites-moi...

@bugeaud
Copy link
Author

bugeaud commented Mar 8, 2023

Il n'y a pas de problème à utiliser une base pour stocker des paramètres applicatifs surtout si cette application a une approche de progiciel ( cas de EHR) et doit rester à la main le plus possibles de non techniciens tels des utilisateurs finaux. C’est donc un bon choix général pour ce type de logiciel.
Mais parmi les paramètres applicatifs certains sont des pré-requis pour faire démarrer l’application et pouvoir accéder à l’administration graphique (ou à une API de gestion).
De ma compréhension actuelle, voici la liste des paramètres pré-requis :

  • nom de machine
  • identifiant d'utilisateur de base
  • mot de passe utilisateur de base
  • serveur de base
  • nom de la base EHR

La question est : où mettre ces paramètres pré-requis d’une façon simple, accessible mais la plus sécurisée possible ?

Ces paramètres doivent être connus de l’administrateur technique (personne ou système automatisé) et ils ne doivent pas être modifiés par d’autres administrateurs.

Dans le cas présent les paramètres peuvent théoriquement être stockés en base ou dans le fichier de config YML.
Mais ces paramètres étant nécessaire pour accéder à la base, dans les faits seul la valeur du fichier de config est utile.

Actuellement, nous avons l’ordre suivant de précédence des paramètres (par ordre de priorité, inverse de l’ordre de chargement) :

  1. Paramètres en base (nécessitant le bon positionnement des pré-requis et le fonctionnement de la base)
  2. Paramètres dans le fichier de config

Dans l’application API-CCAM-NGAP, j’ai introduit (pour test) une nouvelle possibilité, la surcharge par variable d’environnement, nous obtenons ainsi l’ordre de précédence :

  1. Paramètres en base (nécessitant le bon positionnement des pré-requis et le fonctionnement de la base)
  2. Variables d’environements
  3. Paramètres dans le fichier de config

Cette approche m’a permis de positionner les paramètres pré-requis au lancement via les variables d’environnement selon le besoin et de garder un fichier de config le plus générique pouvant être librement mis à la main d’un utilisateur technique qui peut le personnaliser selon ces besoins sur les autres paramètres. Les autres administrateurs gardant enfin le contrôle sur la surcharge via l'IHM.

La dockerisation proposée par @marsante s’appuie sur la génération au lancement du conteneur (de l’app si tu préfères) pour générer un fichier config.yml minimum à la volée. Cette approche plus simple de premier abord ne différentie pas les paramètres pré-requis des autres. Car du fait de l’absence de mécanisme de surcharge dans les fichier YML, l’utilisateur qui veut changer d’autres paramètres du config.yml (hors ceux pré-requis) via config.yml va devoir reprendre en main l’ensemble du fichier (contenant aussi les fameux pré-requis à la main du mécanisme de lancement) ainsi que modifier le mécanisme de lancement pour surcharger le fonctionnement par défaut. Ceci est plus compliqué a gérer et mélenge les genres entre le périmètre applicatif et son déploiement (ici docker). Enfin par exemple, une simple erreur de formatage du config YML va empêcher purement et simplement le chargement de l’application.

Les paramètres pré-requis sont généralement gérés de de façons dans docker via :

  • Les secrets : c’est théoriquement la façon cible de gérer ce type de paramètres en limitant l’accès aux valeurs sensibles. Mais leur manipulation et intégration n’est pas toujours simple.
  • Les variables d’environnements : ce n’est certes pas la plus sécurisée puis-ce que toute personne ayant accès au processus peut lister les valeurs. Mais c’est la façon la plus simple, qui marche avec tous les cas et disposent d’outils dans tous les languages ou dans un grand nombre de fichier de configuration pour y accéder. C’est par exemple la solution choisie pour les images de MySQL/MariaDB.

Je pense qu’il serait intéressant de rajouter dans EHR la récuparation des paramètres pré-requis par variable d’environnement sur le modèle du test de API-CCAM-NGAP, ainsi que de clarifier :

  • L’ordre de précédence des paramètres
  • Le fait que les paramètres pré-requise ne peuvent être utilisés en base

Ceci permettra de simplifier tout lancement automatisé initial de l’application qu’il soit dans ou hors docker. La nette séparation entre paramètres pré-requis et autres permettra aussi de simplifier la gestion et la maintenance des instances de EHR en limitant les erreurs et les opérations.

@marsante
Copy link
Contributor

Pour mon implémentation, il n'y a rien besoin de plus. Ou à la rigueur la présence d'un équivalent wp-content pour WordPress où serait rangé l'ensemble des modules, des plugins, fichiers personnalisés.
Actuellement mon image est construite comme l'image de WordPress. Sans volume, elle permet de tester la dernière version du logiciel. Avec le volume de mappé, elle effectue la première installation si absence de fichier, la mise à jour se fait via le zip (sur wordpress via wordpress). Sur l'image WordPress, on peut également juste mapper le wp-content, la base est gérée par docker, les plugins customs par wordpress. Il faudrait un script pour détecter le changement de version et jouer le dernier fichier sql, il me semble que @bugeaud à ça dans son projet.

Je pense pouvoir proposer un script prochainement pour directement récupérer les mises à jour et modules via l'interface (par contre, je suis nul en interface, il faudra probablement m'aider dessus).

Concernant les avantages de mon image, elle est construite suivant les recommandations de l'image php et n'embarque que le strict nécessaire (830mo). Le ssl, la base de donnée sont gérées par des images officielles. Ça permet de retirer les scripts bash externes, de limiter la maintenance du projet et de bien compartimenter. L'image par ailleurs est lançable sur Windows et macOS ce qui ouvre la possibilité de développer à d'autre écosystème. J'ai optimisé aussi la mise en cache des layers pour que l'image soit plus rapidement buildable et plus économe en ressource. Il n'y a pas besoin de modifier la structure du dépôt du projet. Je peux le proposer comme pour le dossier vagrant dans un dossier ou dans un repo séparé. Mon image peut être lancée avec un docker lancé en root, mais via l'utilisateur non privilégié www-data, ou avec un utilisateur arbitraire ou avec une installation docker rootless.

Le config.yml utilise des variables pour les principaux réglages. Je peux en rajouter au besoin et surtout, elles peuvent être très simplement surchargée, en faisant un docker cp dans un sens puis dans l'autre. Une fois configuré le container n'y touche plus. J'essayerai les secrets dans la semaine voir si ça peut marcher sans modification.
L'entrypoint docker qui gère ça :

#!/bin/bash
set -e

if [ ! -e /var/www/html/public_html/index.php ]; then
    echo "Copie de MedShakeEHR ..."
    cp -pr /usr/src/medshakeehr/* /var/www/html/
    cd /var/www/html && \
    composer install -n --no-plugins --no-scripts --no-cache --no-ansi --no-progress --no-dev -o && \
    cd public_html && \
    composer install -n --no-plugins --no-scripts --no-cache --no-ansi --no-progress --no-dev -o
fi

if [ ! -e /var/www/html/config/config.yml ]; then
    echo "Configuration absente, création ..."
    echo "
sqlRootId: ""
sqlRootPwd: ""
sqlNotCreatDb: true
protocol: $PROTO://
host: $VIRTUAL_HOST
port: $PORT
urlHostSuffixe: ""
webDirectory: /var/www/html/public_html/
stockageLocation: /var/www/html/stockage/
backupLocation: /var/www/html/backups/
workingDirectory: /var/www/html/public_html/workingDirectory/
cookieDomain: $VIRTUAL_HOST
cookieDuration: $COOKIED
fingerprint: $FINGERPRINT
sqlServeur: db
sqlBase: $MYSQL_DATABASE
sqlUser: $MYSQL_USER
sqlPass: $MYSQL_PASSWORD
sqlVarPassword: $SQLVARPSWD
templatesFolder: /var/www/html/templates/
twigEnvironnementCache: false
twigEnvironnementAutoescape: false
twigDebug: false
configForm: ""
        " > /var/www/html/config/config.yml
fi

uid="$(id -u)"
if [ "$uid" = 0 ]; then
    chown -R www-data:www-data /var/www/html/config/config.yml
fi
exec "$@"

Pour tester le projet, c'est toujours là https://github.com/marsante/MedShakeEHR-docker-compose

Bon, comme vous avez vu, j'ai lavé mon cerveau ces derniers jours en faisant pas mal de choses sur le code PHP. C'est amusant car je n'avais pas vu la discussion, mais j'ai passé mon insomnie de la nuit dernière sur le sujet en me disant : "il faudra qu'ils m'expliquent vers quoi il faut aller vraiment pour que ca puisse passer en docker". Il faudra être simplex et me parler le moins possible de Docker : parlez-moi de l'app, de sa problématique multimodule, de sa config. S'il faut revenir à du yaml dans /config, c'est pas compliqué, c'est ce que j'ai toujours voulu faire :-) mais mon coéquipier des débuts a poussé pour une mise en base et surtout une interface graphique de gestion. Bref, dites-moi...

@marsante
Copy link
Contributor

J'ai testé les secrets files sur ma stack ça fonctionne. J'ai ajouté à la stack Watchtower pour automatiser les mises à jour des images, phpMyAdmin pour ceux qui en auraient besoin, Wireguard si besoin d'un VPN. @MedShake j'ai également testé Orthanc, pour le moment, c'est une installation sans mots de passe sur un réseau à part accessible que par le conteneur MedShakeEHR. Je n'ai pas trouvé comment passer un utilisateur et un mot de passe dans l'interface de MedShakeEHR ?

@marsante
Copy link
Contributor

Je viens de penser qu'on peut également comme l'image orthanc, passer le fichier config.yml comme un secret. Dans ce cas-là, il faudra générer dans l'image de base un fichier de configuration exemple, pour que l'utilisateur puisse l'importer facilement sur sa machine avant de le modifier et de le passer dans sa stack. Je ne sais pas ce qui est le mieux entre les deux solutions ?

@MedShake
Copy link
Owner

Question : la v8 semble mure. Que faut il y intégrer pour la dockerisation et ce qui tourne autour y soit présent ?
Si je merge ce PR, c'est ok ?
Merci.

@marsante
Copy link
Contributor

Pour la dockerisation, tout roule finalement de mon côté. Comme je respecte les recommandations des mainteneurs de l'image officielle php, j'avais construit avec le module php mysqli au lieu de pdo_mysql. Les images de la v8 en php8.1 et php8.2 sont dispos sur dockerhub pour tester. @bugeaud ne devrait pas avoir ce problème, car il utilise le paquet d'Ubuntu qui empaquète les deux modules. Je n'ai pas testé par contre.

Le bug de la page des tâches planifiées commun à toutes les dockeurisations de MedShakeEHR et présente aussi sur les conteneurs LXC est toujours présent, mais non dépendant de la v8.

@MedShake
Copy link
Owner

Concrètement, faut-il que je merge ce PR et ça sera bon ?

@marsante
Copy link
Contributor

A priori oui, mais je n'ai pas eu le temps de tester, la mise en place de cette implémentation est assez longue.
Avant de merger il faudrait peut-être enlever les dépendances inutiles, enlever les scripts bash externes redondant avec les commandes docker, et ceux qui nécessitent un accès root. Il y a aussi du code ancien qu'il faudrait nettoyer par exemple sur une image docker non mis à jour depuis cinq ans présente dans un script pour générer un certificat let's encrypt.

@marsante
Copy link
Contributor

J'ai enfin eu le temps de me poser sur la problématique d'installation, mise à jour des modules dans le container. J'ai fait un script qui utilise les mécanismes déjà existant dans le logiciel.

<?php

// Check if the required argument is provided
if ($argc < 2) {
    echo "Usage: php msehr.upgrade.php <repo>\n\n base, chiro, gyneco, general, thermal, mpr, osteo\n";
    exit(1);
}

// Extract the shorthand repo argument
$repoShorthand = $argv[1];

// Define a mapping of shorthand names to GitHub user/repo
$repoMap = [
    'base' => 'MedShake/MedShakeEHR-base',
    'chiro' => 'MedShake/MedShakeEHR-modChiro',
    'gyneco' => 'MedShake/MedShakeEHR-modGynObs',
    'general' => 'MedShake/MedShakeEHR-modMedGe',
    'thermal' => 'MedShake/MedShakeEHR-modMedTher',
    'mpr' => 'MedShake/MedShakeEHR-modMPR',
    'osteo' => 'marsante/MedShakeEHR-modOsteo',
    
];

// Check if the repo shorthand exists in the map
if (!isset($repoMap[$repoShorthand])) {
    echo "Invalid repo shorthand.\n";
    exit(1);
}

// Extract the user and repo from the repo map
$repoInfo = explode('/', $repoMap[$repoShorthand]);
$user = $repoInfo[0];
$repo = $repoInfo[1];

try {
    // Extract the database credentials from config.yml
    $configFile = '/var/www/html/config/config.yml';
    $config = yaml_parse_file($configFile);

    $sqlServer = $config['sqlServeur'];
    $sqlBase = $config['sqlBase'];
    $sqlUser = $config['sqlUser'];
    $sqlPass = $config['sqlPass'];

    // Update the value of the 'state' column in the 'system' table
    $dsn = "mysql:host=$sqlServer;dbname=$sqlBase;charset=utf8mb4";
    $pdo = new PDO($dsn, $sqlUser, $sqlPass);

    // Set PDO error mode to exception
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "UPDATE system SET value = 'maintenance' WHERE name = 'state'";
    $pdo->exec($sql);

    // Retrieve the latest release tag name using cURL
    $apiUrl = "https://api.github.com/repos/$user/$repo/releases/latest";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $apiUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3');
    $response = curl_exec($ch);
    curl_close($ch);

    $releaseData = json_decode($response, true);
    $latestRelease = $releaseData['tag_name'];

    // Print the latest release tag name
    echo "Dernière version : $latestRelease\n";

    // Download and extract the release from GitHub
    $version = substr($latestRelease, 1); // Remove the 'v' prefix
    $tarFile = "/tmp/$latestRelease.tar.gz";
    $downloadUrl = "https://github.com/$user/$repo/archive/$latestRelease.tar.gz";

    // Download the release tar.gz file using cURL
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $downloadUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    $response = curl_exec($ch);
    curl_close($ch);

    // Save the downloaded tar.gz file
    file_put_contents($tarFile, $response);

    // Extract the release contents using tar
    $extractDir = "/tmp/$repo-$version";
    $extractCommand = "tar -xzf $tarFile -C /tmp";
    exec($extractCommand);

    // Move the extracted files to the target directory
    $moveCommand = "cp -r -f $extractDir/* /var/www/html/";
    exec($moveCommand);

    // Print a success message
    echo "La copie c'est bien déroulée, connectez vous à votre compte administrateur pour appliquer la mise à jour.\n";

} catch (Exception $e) {
    // Handle any errors
    echo "Erreur: " . $e->getMessage() . "\n";
}

?>

Ça copie la dernière version du module concerné et met medshakeehr en mode maintenance. En se déconnectant / connectant en tant qu'admin ça met à jour / installe. Les droits ont l'air d'être ok que ce soit exécuté par root ou un utilisateur arbitraire. J'ai testé sur Linux, Windows et macOS avec succès. Je suis toujours aussi mauvais en PHP il y a probablement moyen de faire plus propre.

Pour tester :

git clone https://github.com/marsante/MedShakeEHR-docker-compose
cd MedShakeEHR-docker-compose
cp sample.env .env
nano .env
nano docker-compose.yml
docker-compose up -d
ou
docker compose up -d 

puis rendez-vous sur https://msehr.localhost/install.php pour configurer le premier utilisateur admin

ensuite pour mettre à jour / installer :

docker exec -ti msehr php /usr/local/bin/msehr.upgrade.php base

les arguments disponibles sont : base, chiro, gyneco, general, thermal, mpr, osteo

J'avais commencé à nettoyer aussi le projet de bugeaud, mais j'ai peur que ça passe par une phase d'incompatibilité avec le projet existant donc j'ai arrêté.

Concernant le script est ce qu'il serait intéressant de le livrer directement dans les scripts du module base ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants