Installation Docker
Afin de faciliter l’installation du serveur SAINet, un container est mis à disposition sur Docker Hub (dès la version 4.9). En utilisant cette image, combinée aux autres services nécessaires, aucune installation particulière (en dehors de Docker) n’est nécessaire sur la machine hôte.
Paramètres
Afin de pouvoir configurer SAINet, les paramètres ci-dessous doivent être connus au préalable.
Paramètre | Variable | Description |
---|---|---|
user | SAINET_UPDATE_USERNAME |
Identifiant pour accéder aux paquets d’installation et de mises à jour. |
password | SAINET_UPDATE_PASSWORD |
Mot de passe pour accéder aux paquets d’installation et de mises à jour. |
customer id | SAINET_CUSTOMER_FILE |
Identifiant du client au sein de SAINet. |
environment id | SAINET_ENV_NAME |
Identifiant de l’environnement d’installation. Cette valeur est en lien avec le serveur sur lequel l’application va être installée. |
mobile | SAINET_MOBILE_ENABLED |
Détermine si la partie mobile doit être déployée, notamment pour permettre l’accès à l’application par browser / tablette. |
Base de données | SAINET_DATABASE_MYSQL_* |
Paramètres de connexion à la base de données. |
Configuration système
Sous Debian, 2 paquets doivent être installés:
apt-get install docker docker-compose
systemctl start docker
L’utilisateur courant (<user>
) doit ensuite faire partie du groupe docker
afin de pouvoir gérer le service. Avec l’utilisateur
root
, exécuter la commande suivante:
gpasswd -a <user> docker
L’utilisateur devra ensuite se reconnecter afin d’avoir ses accès à jour.
Pour éviter de se reconnecter, il est possible d’utiliser la commande newgrp docker
.
Configuration automatique
Un projet est mis à disposition par SAI ERP pour automatiser l’initialisation et la mise à jour de SAINet dans un environnement Docker.
Initialisation
Si le projet git est directement utilisé, commencer par les étapes suivantes:
- Cloner le projet (avec HTTPS).
- Passer sur la branche nécessaire (
git checkout stable/4.9.x
).
Si les fichiers ont été envoyés par mail au préalable, l’étape ci-dessus n’est pas nécessaire.
Lorsque SAINet est déployé pour la première fois:
- Remplacer les
<to_define>
par les valeurs appropriées dansdocker-compose.yml
. - Exécuter
./sainet-up.sh
.
A la fin du script, en pressant Enter, les logs Docker sont affichés directement dans la console afin de pouvoir suivre le déploiement de SAINet. A la fin du déploiement, les logs montrent ceci:
================================================
SAINet Embedded Server version 4.9.4.
The domain payara is now up and running. (inst:PYA, env:#local)
The GlassFish/Payara installation dir is /tmp/gfembed14043435345614509593tmp
The SAINet runtime dir is <runtime>
Ports used: HTTP=9090, HTTPS=9191, ADMIN=5858
URL: http://<url>/SNV4SRV-ws-war/EPS
Host: sagittarius/127.0.1.1
================================================
You can use <ctrl> + C to shut it down.
Cela indique que le serveur SAINet est prêt et qu’il faut simplement faire <ctrl> + C
pour quitter l’affichage des logs. Cela ne
va pas arrêter le serveur SAINet comme lors d’une exécution directe ! La commande <ctrl> + C
peut être faite à tout moment sans impact,
comme lorsque l’on utilise la commande docker logs -f <container_id>
.
Désormais, SAINet est entièrement fonctionnel avec les services nécessaires. Après l’initialisation,
il est possible de se connecter à SAINet avec les identifiants saierp
/ bootStrap373746
.
Mise à jour majeure
Il est fortement recommandé de faire une sauvegarde de la base de données avant toute mise à jour majeure ! Le script sainet-up.sh
propose d’en faire une automatiquement.
Lorsqu’une mise à jour majeure doit être effectuée, cela implique généralement des modifications de système. La procédure suivante doit être appliquée:
- Stocker les modifications courante (
git stash
). - Mettre à jour (
git pull
) et passer sur la branche désirée (git checkout stable/4.9.x
). - Réappliquer les modifications (
git stash pop
) et corriger les éventuels conflits. - (Une fois les conflits corrigés, revenir dans un état normal (
git add -u . && git reset
)). - Exécuter
./sainet-up.sh
.
Dans le cas où git n’est pas utilisé, il est recommandé d’utiliser les nouveaux fichiers et de reprendre les configurations nécessaires avant d’exécuter ./sainet-up.sh
.
Le script va prendre en charge les migrations nécessaires (surtout sur la base de données) et redémarrer les containers.
Configuration minimale
Voici une configuration minimale (docker-compose.yml
) permettant de démarrer SAINet:
version: "3.0"
services:
sainet_app:
restart: always
image: saierp/sainet:4.9
volumes:
- "./sainet:/sainet"
environment:
# java options
- JAVA_OPTIONS=-Xmx4096m
# database configuration
- SAINET_DATABASE_MYSQL_HOST=<to_define>
- SAINET_DATABASE_MYSQL_SCHEMA=<to_define>
- SAINET_DATABASE_MYSQL_USER=<to_define>
- SAINET_DATABASE_MYSQL_PASSWORD=<to_define>
# global configuration
- SAINET_CUSTOMER_FILE=<to_define>
- SAINET_ENV_NAME=<to_define>
#- SAINET_EXTERNAL_URL=<to_define>
# update configuration
- SAINET_UPDATE_USERNAME=<to_define>
- SAINET_UPDATE_PASSWORD=<to_define>
- SAINET_UPDATE_MODE=release
# backup configuration
- SAINET_BACKUP_UPDATE_ENABLED=true
- SAINET_BACKUP_CRON_CONFIG=0 2 * * *
- SAINET_BACKUP_RETENTION_DAYS=7
Le dossier /sainet
doit être utilisé en tant que volume car celui-ci contient tous les fichiers qui doivent être persistants.
Les variables d’environnement principales sont les suivantes:
Variable | Description |
---|---|
JAVA_OPTIONS |
Options spécifiques à Java. Il est recommandé de spécifier au moins la propriété -Xmx avec une valeur minimale de 2048m . |
SAINET_DATABASE_MYSQL_* |
Configuration d’accès à la base de données. |
SAINET_CUSTOMER_FILE |
Identifiant du client au sein de SAINet, transmis par SAI ERP. |
SAINET_ENV_NAME |
Identifiant de l’environnement d’installation, transmis par SAI ERP. Cette valeur est en lien avec le serveur sur lequel l’application va être installée. |
SAINET_EXTERNAL_URL |
Permet de spécifier l’URL externe complète par laquelle le serveur SAINet peut être atteint (par exemple https://sainet.mydomain.com/SNV4SRV-ws-war/EPS ). |
SAINET_UPDATE_USERNAME / SAINET_UPDATE_PASSWORD |
Identifiant / mot de passe pour les mises à jour automatiques, transmis par SAI ERP. Ces valeurs sont nécessaires pour initialiser l’image. |
SAINET_BACKUP_UPDATE_ENABLED |
Détermine si une sauvegarde de la base de données doit être effectuée avant d’appliquer une mise à jour automatique. Cela peut s’avérer superflu, voir problématique si la base de données est volumineuse (>= 10 Go). |
SAINET_BACKUP_CRON_CONFIG |
Configuration cron pour les mises à jour automatiques. Cette variable peut être supprimée pour désactiver les sauvegardes automatiques. |
SAINET_BACKUP_RETENTION_DAYS |
Nombre de jours de rétention des sauvegardes automatiques. Cette variable peut être mise à zéro pour ne pas supprimer les sauvegardes, ou simplement supprimée pour désactiver les sauvegardes automatiques. |
Le container offre la possibilité de faire des sauvegardes automatiques, mais cela reste basique et n’est pas suffisant pour un serveur de production.
Configuration complète
La configuration ci-dessous déclare plusieurs services utilisés par SAINet:
ID | Description | Volume |
---|---|---|
sainet_db | Base de données | sainet/mariadb |
sainet_redis | Cache Redis (lorsque le mobile est déployé, cf SAINET_MOBILE_ENABLED |
aucun |
sainet_traefik | Serveur HTTP/HTTPS pour la gestion des communications et certificats SSL | sainet/certificates |
sainet_app | Serveur SAINet | sainet/app |
Il est nécessaire de créer les dossiers sainet/mariadb
, sainet/certificates
et sainet/app
.
version: "3.0"
services:
sainet_app:
restart: always
image: saierp/sainet:4.9
depends_on:
- sainet_db
- sainet_redis
volumes:
- "./sainet/app:/sainet"
environment:
# java options
- JAVA_OPTIONS=-Xmx4096m
# database configuration
- SAINET_DATABASE_MYSQL_HOST=sainet_db
- SAINET_DATABASE_MYSQL_SCHEMA=sainet_prod
- SAINET_DATABASE_MYSQL_USER=dbuser
- SAINET_DATABASE_MYSQL_PASSWORD=dbpassword
# global configuration
- SAINET_CUSTOMER_FILE=<to_define>
- SAINET_ENV_NAME=<to_define>
#- SAINET_EXTERNAL_URL=<to_define>
# mobile configuration
- SAINET_MOBILE_ENABLED=true
- SAINET_REDIS_URL=redis://sainet_redis
# update configuration
- SAINET_UPDATE_USERNAME=<to_define>
- SAINET_UPDATE_PASSWORD=<to_define>
- SAINET_UPDATE_MODE=release
# backup configuration
- SAINET_BACKUP_UPDATE_ENABLED=true
- SAINET_BACKUP_CRON_CONFIG=0 2 * * *
- SAINET_BACKUP_RETENTION_DAYS=7
labels:
# URL mapping
- "traefik.http.routers.sainet_app.rule=Host(`<to_define>`)"
#- "traefik.http.routers.sainet_app.rule=PathPrefix(`/`)"
- "traefik.http.routers.sainet_app.entrypoints=websecure"
- "traefik.http.services.sainet_app.loadbalancer.server.port=9090"
- "traefik.http.routers.sainet_app.tls.certresolver=le"
sainet_db:
restart: always
image: mariadb:10.4
volumes:
- "./sainet/mariadb:/var/lib/mysql"
environment:
- MYSQL_DATABASE=sainet_prod
- MYSQL_USER=dbuser
- MYSQL_PASSWORD=dbpassword
- MYSQL_ROOT_PASSWORD=dbroot
command:
- --max-allowed-packet=1024M
- --default-time-zone=Europe/Zurich
labels:
- "traefik.enable=false"
sainet_redis:
restart: always
image: redis:6-alpine
labels:
- "traefik.enable=false"
sainet_traefik:
restart: always
image: traefik:v2.3
depends_on:
- sainet_app
command:
- --providers.docker
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --certificatesresolvers.le.acme.email=<to_define>
- --certificatesresolvers.le.acme.storage=/sainet/certificates/acme.json
- --certificatesresolvers.le.acme.caserver=https://acme-v02.api.letsencrypt.org/directory
- --certificatesresolvers.le.acme.tlschallenge=true
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "./sainet/certificates:/sainet/certificates"
ports:
- "80:80"
- "443:443"
labels:
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.redirs.entrypoints=web"
- "traefik.http.routers.redirs.middlewares=redirect-to-https"
Service MariaDB
Ce service gère la base de données de SAINet.
- La TimeZone (
--default-time-zone
) doit être mise àEurope/Zurich
(nécessite un chargement manuel des TimeZone dans un container). - L’option
--max-allowed-packet
doit être mise à1024M
afin de pouvoir dumper/restaurer la base de données (certaines tables contiennent de gros fichiers). - Lors d’une mise à jour de la base, la commande
mysql_upgrade
doit être exécutée.
Ces opérations sont gérées automatiquement par le script sainet-up.sh.
Service Traefik
Ce service gère toutes les communications avec les requêtes externes.
- Les connexions HTTP sont automatiquement redirigées en HTTPS.
- En arrière-plan, les requêtes sont redirigées sur SAINet (port 9090).
- Le certificat SSL est créé/renouvellé automatiquement (voir ci-dessous).
Certificats dynamiques
La configuration ci-dessus utilise Let’s Encrypt afin d’obtenir un certificat SSL. Celui-ci sera renouvellé automatiquement par Traefik.
Afin que le certificat SSL puisse être créé/renouvelé automatiquement, il est nécessaire que la règle de routing dans
le label traefik.http.routers.sainet_app.rule
permette à Traefik d’identifier l’hôte. Typiquement, voici un label qui fonctionnera:
traefik.http.routers.sainet_app.rule=Host(`sainet.mydomain.com`)
Au contraire, l’utilisation de la règle ci-dessous ne permettra pas à Traefik d’obtenir un certificat SSL valide et fournira un certificat auto-signé (qui proviquera des alertes lorsque SAINet est accédé à travers un navigateur Web):
traefik.http.routers.sainet_app.rule=PathPrefix(`/`)
Lorsque la règle Host(sainet.mydomain.com)
est utilisée, il ne sera pas possible d’accéder à SAINet via une autre URL que https://sainet.mydomain.com
(typiquement localhost
), Traefik retournera une erreur 404. Dans ce cas, il faudra temporairement utiliser la règle PathPrefix('/')
.
Certificats statiques
Lorsque les certificats ne sont pas renouvelables automatiquement via Let’s Encrypt ou un autre organisme
supporté par traefik, il est possible de configurer ce dernier pour utiliser des certificats statiques. Pour ce
faire, appliquer la procédure suivante (dans le service sainet_traefik
):
- Enlever toutes les options
--certificatesresolvers.*
. - Ajouter l’option
--providers.file.directory=/certificates/config
juste après l’option--providers.docker
. - Ajouter le volume
./sainet/certificates:/certificates
. - Créer les dossiers
sainet/certificates/config
etsainet/certificates/files
. - Placer les fichiers
pem
etkey
danssainet/certificates/files
. - Créer le fichier
sainet/certificates/config/tls.yml
avec le contenu suivant (ajuster<file>
avec les noms de fichiers corrects):
tls:
certificates:
- certFile: /certificates/files/<file>.pem
keyFile: /certificates/files/<file>.key
Création des containers
Pour créer les différents containers:
docker-compose pull
docker-compose up -d
Une fois le serveur SAINet démarré, il est possible de se connecter à SAINet avec les identifiants saierp
/ bootStrap373746
.
Pour suivre les logs de démarrage du service SAINet, utiliser la commande docker logs -f $(docker ps | grep sainet_app | awk '{print $1}')
Mise à jour majeure
Il est fortement recommandé de faire une sauvegarde de la base de données avant toute mise à jour majeure !
Afin d’appliquer une mise à jour majeure, il suffit de changer la version du container SAINet dans docker-compose.yml
et
de relancer la commande docker-compose up -d
. La nouvelle version sera automatiquement téléchargée et appliquée.
Importation
Dans un processus de migration (typiquement pour la préparation d’une mise à jour majeure), il est nécessaire de pouvoir importer les
données actuellement en production sur un serveur de test. Une fois les données remontées, il suffit de redémarrer le container sainet_app
et ce dernier appliquera automatiquement les mises à jour nécessaires.
La base de données importée doit provenir d’un serveur avec une version antérieure ou égale à celui déployé dans le container, sinon ce dernier refusera de démarrer.
Concernant la GED, les fichiers peuvent simplement être copiés dans le répertoire ./sainet/app/runtime/edms/ged
.
Version actuelle
Dans un container docker, il est possible d’obtenir la version actuelle de SAINet avec la commande suivante:
docker exec <container_id> java -jar /sainet/sainet-server.jar --version
Le <container_id>
peut être obtenu avec la commande docker ps --filter "name=sainet_app" --format "{{.ID}}"
.
Mise à jour forcée
Si la mise à jour doit vraiment être forcée, la solution la plus simple consiste à supprimer le fichier ./sainet/app/sainet-server.jar
et à relancer
le container. Cela provoquera le téléchargement de la dernière version mineure du type de version configuré.
Pour ce genre de cas, il est donc conseillé de spécifier SAINET_UPDATE_MODE=rc
(voire même SAINET_UPDATE_MODE=snapshot
si nécessaire)
afin que le container puisse redémarrer sur une version plus récente et évite de forcer un rollback.
Avec cette procédure, la mise à jour sera forcée, même si la base de données est plus récente. Cela peut provoquer un rollback de certaines modifications et conduire à des incohérences.
En utilisant le projet, il est possible de faire cela en utilisant la commande suivante:
./sainet-up.sh --force-update
Sauvegarde
Lorsque la configuration complète est utilisée, tous les fichiers persistants se trouvent dans le répertoire ./sainet
. Par conséquent,
ce répertoire peut simplement être copié sur un emplacement physique différent.
Selon la valeur des variables SAINET_BACKUP_RETENTION_DAYS
et SAINET_BACKUP_UPDATE_ENABLED
, les sauvegardes automatiques de la base de données sont conservés dans ./sainet/app/backups
et ./sainet/app/update_backups
.
Sauvegarde manuelle
Il est possible d’effectuer une sauvegarde manuelle de la base de données avec la commande suivante:
docker exec <container_id> /bin/bash /bin/backup.sh
Le nom du fichier de sauvegarde ne contenant que la date du jour, si la commande est lancée plusieurs fois, la sauvegarde du jour sera écrasée.
Restauration
Pour restaurer une sauvegarde complète, il suffit de remettre le contenu sauvegardé du dossier ./sainet
en place et de simplement relancer
les containers avec la commande docker-compose up -d
.