Zigbee2mqtt : Image docker de test basée Gladys v4

Tu utilises bien la variable SQLITE_FILE_PATH (comme dans ton docker-compose plus haut) ?

"SQLITE_FILE_PATH=/var/lib/gladys-z2m/gladys-z2m-production.db"

Tu peux me donner le résultat des commandes suivantes ?

docker inspect -f '{{ .Mounts }}' gladys-z2m-mqtt

docker inspect -f '{{ .Mounts }}' gladys-z2m-zigbee2mqtt

Ma commande est la suivante :

    docker run -d \
    --log-opt max-size=10m \
    --restart=always \
    --privileged \
    --network=host \
    --name GladysZigbee2mqtt \
    -e NODE_ENV=production \
    -e SERVER_PORT=1080 \
    -e TZ=Europe/Paris \
    -e SQLITE_FILE_PATH=/var/lib/gladysassistant/gladys-zigbee2mqtt.db \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /var/lib/z2m-test:/var/lib/gladysassistant \
    -v /dev:/dev \
    -v /run/udev:/run/udev:ro \
    cicoub13/gladys:dev-zigbee2mqtt
$ docker inspect -f '{{ .Mounts }}' gladys-z2m-mqtt
[{volume 227a9e1e87d118c13a7d214c28395292e7b69fae2abcf2b330821ceb31add32d /var/lib/docker/volumes/227a9e1e87d118c13a7d214c28395292e7b69fae2abcf2b330821ceb31add32d/_data /mosquitto/data local  true } {bind  /var/lib/gladysassistant/zigbee2mqtt/mqtt /mosquitto/config   true rprivate} {volume c30bc5eede272b937d1e6bb1dd46c224f576b9d3c294bec90ed8cd6cca80926c /var/lib/docker/volumes/c30bc5eede272b937d1e6bb1dd46c224f576b9d3c294bec90ed8cd6cca80926c/_data /mosquitto/log local  true }]

Concernant la deuxième commande je ne peux pas te fournir de réponse puisque Z2M ne s’est pas créé.

$ docker inspect -f '{{ .Mounts }}' gladys-z2m-zigbee2mqtt
Error: No such object: gladys-z2m-zigbee2mqtt

OK, j’ai compris :sweat_smile:

Quand tu mets ces deux options :

  • -v /var/lib/z2m-test:/var/lib/gladysassistant
  • SQLITE_FILE_PATH=/var/lib/gladysassistant/gladys-zigbee2mqtt.db

Tu montes ton dossier host /var/lib/z2m-test dans le container en tant que /var/lib/gladysassistant
Puis tu dis à Gladys de fonctionner avec /var/lib/gladysassistant, ce qu’il fait quand il crée les fichiers de configuration Mosquito et Z2M. C’est d’ailleurs pour cela que tu retrouves bien les fichiers de configuration dans /var/lib/z2m-test dans ton host.

Lorsque Gladys crée les autres containers (Mosquito et Z2M), il utilise la variable SQLITE_FILE_PATH pour monter les volumes. Donc le /var/lib/gladysassistant de ton host… C’est là où ça ne va pas. Je ne sais pas comment détecter que /var/lib/gladysassistant est en fait un montage de /var/lib/z2m-test.

Je te propose d’essayer avec ce fichier docker-compose :thinking: :

docker run -d \
    --log-opt max-size=10m \
    --restart=always \
    --privileged \
    --network=host \
    --name GladysZigbee2mqtt \
    -e NODE_ENV=production \
    -e SERVER_PORT=1080 \
    -e TZ=Europe/Paris \
    -e SQLITE_FILE_PATH=/var/lib/z2m-test/gladys-zigbee2mqtt.db \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /var/lib/z2m-test:/var/lib/z2m-test \
    -v /dev:/dev \
    -v /run/udev:/run/udev:ro \
    cicoub13/gladys:dev-zigbee2mqtt
1 « J'aime »

Les fichiers de configuration doivent être écrits par Gladys sur ton host quelque part. J’ai décidé d’utiliser SQLITE_FILE_PATH comme le dossier où écrire ces fichiers. Mais sans penser au cas où tu montes ce dossier depuis un autre path sur ton host.

Mais peut-être qu’il faudrait utiliser une autre variable pour cela ? Genre HOST_PATH_Z2M_FILES ?

La on arrive dans l’exotique, en standard c’est /var/lib/gladysassistant

On gérera pas tout les cas et on pourra pas rajouter une variable aux instances de production

1 « J'aime »

Je ne suis pas d’accord, toutes les images que j’ai utilisé jusqu’à maintenant te permette d’utiliser un chemin de persistance différent de chemin officiel.

Le réel problème qu’on a ici c’est de devoir spécifier plusieurs chemin si on utilise un chemin alternatif.

A-t-on vraiment besoin de spécifier un chemin pour la base données, ne peut on pas tout simplement mettre tous les fichiers au sein du conteneur dans un même dossier, ici surement /var/lib/gladysassistant donc fixer la valeur du SQLITE_FILE_PATH (et donc de le supprimer de la config et ensuite simplement demander à l’utilisateur de remplir la valeur PERSISTANCE_FOLDER (par exemple) qui ferait un mapping entre le dossier du conteneur et l’hote ?

La on est dans un cas ou si on veut tester plusieurs images de gladys on doit modifier tous les chemins de la config, le SQLITE_FILE_PATH puis le dossier dans le conteneur et le dossier de mapping sur l’hôte.

Effectivement tout fonctionne bien maintenant, c’est vrai que comme mon message l’indique d’au dessus on soit obligé de changer trois valeurs pour faire ça, mais tous les problèmes sont résolus.

Les deux types d’appareils aquara que j’ai fonctionnent bien, le chemin des fichiers est bien modifié comme il faut et la remontée des infos se fait bien sur le dashboard, bravo pour le taff à tout ceux qui ont bossé sur cette intégration. :slight_smile:

Relis moi, j’ai pas dit que techniquement c’était pas possible. J’ai juste dit qu’on ne peut pas exploser toutes les instances de gladys en production. Car faire ce changement ça pète tout.

Exact cas particulier, pas en production. La commande de @cicoub13 marche parfaitement car tous les paths correspondent.

Bref c’est de l’héritage.

1 « J'aime »

Pourquoi ne pas simplement faire comme l’exposition des ports avec Docker ?
Par exemple, par défaut une application se lance sur le port 3456, mais tu veux exposer le port 80 publiquement, alors tu utilises l’option -p 80:3456.

Pour moi il faut faire pareil dans Gladys : tout est stocké dans le conteneur par défaut dans /var/lib/gladysassistant et la modification du chemin passe par la modification du chemin du conteneur : -v /data/exemple/Gladys:/var/lib/gladysassistant.

Ça me semble plus simple faire et à comprendre !

1 « J'aime »

Bah c’est le cas pour Gladys, le problème n’est pas là.

Il faudrai pourvoir depuis le conteneur récupérer le bind (-v) pour le communiquer aux autres conteneurs. Si on gère ça ça résoud tout.

Objectif: récupérer depuis le conteneur le bind sur /var/lib/gladysassistant

@cicoub13 Je viens de tester rapidement sans allez vraiment au bout un petit bout de js avec la lib qu’on utilise.

var Docker = require('dockerode');
var docker = new Docker({socketPath: '/var/run/docker.sock'});
// ICI on peut remplacer gladys par os.hostname
var container = docker.getContainer('gladys');

 container.inspect(function (err, data) {
         var string = JSON.stringify(data);
         var objectValue = JSON.parse(string);
         console.log(objectValue['HostConfig']['Binds']);
});

Me retourne les mounts standards

[
  '/var/run/docker.sock:/var/run/docker.sock',
  '/var/lib/gladysassistant:/var/lib/gladysassistant'
]

Une petite regex pour récupérer le bind côté host et ça devrai résoudre ce point ?

Pas mal. J’aime bien l’idée. Mais comment je récupère le bon ? Vu qu’on peut monter n’importe quel dossier du host et n’importe quel dossier dans docker (avec SQLITE_FILE_PATH).
Et même monter plusieurs dossiers.

Et ça commence à devenir compliqué :smile:

J’ai envie de dire le sql c’est la db peut importe.

Gladys dans tout les cas ( pour la partie mqtt et zigbee ) doit écrire sa conf dans /var/lib/gladysassystant , là on est dans le conteneur.
En récupérant le bind côté host on peut s’en servir pour créer les autres conteneurs et gérer la persistance.

Mon précédant post n’est pas le bon exemple car je bind le même path. Mais par exemple si je prends le cas de @Albenss

-v /var/lib/z2m-test:/var/lib/gladysassistant

Mon bout de js va retourner

[
  '/var/run/docker.sock:/var/run/docker.sock',
  '/var/lib/z2m-test:/var/lib/gladysassistant'
]

D’ailleurs j’ai tester vite fait une regex ( que j’ai pas réussi à implémenter en js mais c’est pas le sujet :sweat_smile: )

EDIT: regex101 propose un générateur de code pour tester. :expressionless: et ça fait le taf

1 « J'aime »

@VonOx ça me semble bien cette solution :slight_smile: Effectivement, ça éviterait de forcer l’utilisateur à mettre ces données dans /var/lib/gladysassistant sur l’host si il n’a pas ce dossier de dispo.

Seule remarque, côté JS il faudra faire tourner la regex avec le basePath et pas /var/lib/gladysassistant, et on sera bon!

@cicoub13 tu intègre ça à la PR Zigbee2mqtt ?

A part ça, je suis bon pour merger la PR zigbee2mqtt, j’ai vu ta vidéo @cicoub13 et ça dépote! C’est vraiment du beau boulot rien à redire :slight_smile: Congrats à tous ceux qui ont travaillé sur cette PR c’est génial !

Le basepath ? Déso j’ai pas compris

EDIT: Ah le SQLITE_FILE_PATH ?

Je peux aussi faire une PR rapidement pour ajouter la fonction dans la lib/system pour éviter de charger celle de cicoub

EDIT2: Basé sur le getNetworkMode c’est crado car eslint cri un peu mais voilà une base @cicoub13

const get = require('get-value');
const { PlatformNotCompatible } = require('../../utils/coreErrors');
const { exec } = require('../../utils/childProcess');

/**
 * @description Get Gladys host bind folder from docker environment.
 * @returns {Promise} Resolve with host path.
 * @example
 * const getDockerHostFolder = await this.getDockerHostFolder();
 */
async function getDockerHostFolder() {
  if (!this.dockerode) {
    throw new PlatformNotCompatible('SYSTEM_NOT_RUNNING_DOCKER');
  }

  if (!this.dockerHostFolder) {
    const regex = /([\/[\w-]+]*):\/var\/lib\/gladysassistant/gm;
    const cmdResult = await exec('head -1 /proc/self/cgroup | cut -d/ -f3');
    const [containerId] = cmdResult.split('\n');
    const gladysContainer = this.dockerode.getContainer(containerId);
    const gladysContainerInspect = await gladysContainer.inspect();
    const bindPaths = get(gladysContainerInspect, 'HostConfig.Binds');
    const matches = bindPaths.matchAll(regex);
    this.dockerHostFolder = matches[0];
  }

  return this.dockerHostFolder;
}

module.exports = {
  getDockerHostFolder,
};

Oui, utiliser la fonction basePath qu’a fait @cicoub13 dans sa PR qui utilise le SQLITE_FILE_PATH pour trouver le dossier utilisé en interne.

C’est en cours :wink: c’est compliqué de tester tous les cas (plusieurs dockers qui contiennent le mot gladys, pas de volume monté, …)

1 « J'aime »

Faut faire par id ( comme la fonction getnetworkmode)

2 « J'aime »

C’est là où on fait erreur !

En interne ça doit toujours être /var/lib/gladysassistant. ( standard à définir )
Cette variable ( SQLITE_FILE_PATH ) doit être par défaut dans l’image avec ce path.

Là on doit gérer cette variable ( utilisée que pour la db ) et le bind de persistance

Pour la création des conteneurs de service c’est seulement le bind host qui compte , peut importe où est la DB dans le conteneur.

Y’a 2 sujets:

  • Comment gérer les “datas” gladys dans l’image => /var/lib/gladysassistant en standard
  • Comment créer des conteneurs de service qui utilise le même bind host path que gladys => la fonction que je propose ( /???/??? bindé sur /var/lib/gladysassistant )

Non, parce qu’en local sur nos machines, ou hors docker tu veux le mettre ou tu veux !

Après c’est vrai que hors docker ou sur nos machines on fait pas pop des containers du coup