NEWS
Docker (VM) Container mit ioB (LXC) restart
-
Hallo zusammen,
meine Gegebenheiten:
- ioBroker auf Proxmox in eigenen LXC, 10.68.xx.yyy
- Docker auf Proxmox in VM, 10.68.xx.zzz, darauf laufen der portainer.io und drei Container.
Diese drei Container sollen nun mit dem ioB überwacht und ggf ein restart durchgeführt werden.
Leider habe ich keinen Ahnung wie ich mit ioB auf den portainer.io zugreifen soll, gibt es da schon Lösungsansätze oder Ideen dazu?
Danke Euch!
-
@australien der Linux-Adapter kann genutzt werden, um beliebige Kommandozeilen-Kommandos auszuführen ...
https://github.com/Scrounger/ioBroker.linux-control
Das würde aber bedeuten, dass man sich mit der Kommandozeile von Docker beschäftigen muss.
-
portainer hat eine api mit der du alles steuern kannst dazu musst du die als erstes ein access token holen
https://docs.portainer.io/api/examples#authenticate-against-the-api-using-the-admin-account
mit dem folgenden url schema und dem access token bspw dann auch ein container neu starten
POST http://10.68.xx.zzz:9000/api/endpoints/1/docker/containers/<container_id>/restart Authorization: Bearer <jwt>
portainer reicht sozusagen die docker api mit http://10.68.xx.zzz:9000/api/endpoints/1/docker/ durch
https://docs.docker.com/reference/api/engine/version/v1.41/#tag/Container/operation/ContainerRestart -
@oliverio jetzt habe ich mir das angeschaut, leider sehe ich nur einen großen Bahnhof.
Wie kann ich das in ioB umsetzten?
Genauer gesagt, ein Container in portainer.io schmiert hinundwieder ab, dieser soll dann neu gestartet werden. Ersichtlich ist das insovern, das eingewisser DP keinen gültigen Wert liefert. -
Zunächst, der Fehler im Container sollte eigentlich als erstes analysiert und behoben werden, so dass solche Schritte nicht notwendig sein müssten. Das ist ja mehr oder weniger nichts anderes wie der Fußtritt gegen das Gerät.
Ich hab mal ChatGPT gefragt, eine fertige Funktion für dich zu formulieren:
// Restart a Docker container via Portainer API // Requires Node 18+ (native fetch) or node-fetch polyfill const PORTAINER_URL = "http://portainer.example.com:9000"; // deine Portainer-URL const API_TOKEN = "xxx_your_portainer_api_token_xxx"; // dein API-Token const ENDPOINT_ID = 1; // meistens 1 const CONTAINER_ID = "mein_container"; // Container Name oder ID async function restartContainer() { const url = `${PORTAINER_URL}/api/endpoints/${ENDPOINT_ID}/docker/containers/${CONTAINER_ID}/restart`; try { const res = await fetch(url, { method: "POST", headers: { "Authorization": `Bearer ${API_TOKEN}`, "Content-Type": "application/json" } }); if (res.ok) { console.log(`✅ Container "${CONTAINER_ID}" wurde erfolgreich neu gestartet.`); } else { const text = await res.text(); console.error(`❌ Fehler: ${res.status} - ${text}`); } } catch (err) { console.error("⚠️ Netzwerkfehler:", err); } } restartContainer();
Die Funktion sieht gut aus, hab sie aber selbst nicht getestet.
Du musst eigentlich nur die ersten paar Zeilen ausfüllen.PORTAINER_URL Sollte eigentlich klar sein, die URL, mit der du den Container bei dir aufrufst.
API_TOKEN den Token musst du dir im portainer erzeugen unter oben rechts auf deinen Anmeldenamen, dann mein myaccount auswählen.
Da gibt es dann einen Abschnitt, wo du dir das erzeugen lassen kannst.
CONTAINER_ID diese findest du im portainer auf der Statusseite des Containers ganz oben -
@oliverio danke für Deine Hilfe!
Ich habe mich nun auch etwas mit KI und dem Thema beschäftigt.
Leider kann ich meine EndpointID nirgends wo finden und wollte dies mit folgendem finden lassen:const https = require('https'); // Konfiguration const PORTAINER_HOST = '10.68.xx.yy'; const PORTAINER_PORT = 9443; const API_TOKEN = 'XxXxXxXx'; // Hier deinen gültigen Token eintragen const ENDPOINT_ID = 1; const CONTAINER_ID = 'Cont_ID'; // Funktion, um Container neu zu starten function restartContainer() { const options = { hostname: PORTAINER_HOST, port: PORTAINER_PORT, path: `/api/endpoints/${ENDPOINT_ID}/docker/containers/${CONTAINER_ID}/restart`, method: 'POST', headers: { "Authorization": `Bearer ${API_TOKEN}`, "Content-Type": "application/json" }, rejectUnauthorized: false // Self-signed Zertifikat akzeptieren }; const req = https.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { if (res.statusCode >= 200 && res.statusCode < 300) { console.log(`✅ Container "${CONTAINER_ID}" wurde erfolgreich neu gestartet.`); } else { console.error(`❌ Fehler beim Neustart: ${res.statusCode} - ${data}`); } }); }); req.on('error', (err) => { console.error(`⚠️ Netzwerkfehler: ${err}`); }); req.end(); } // Direkt beim Start ausführen (optional) restartContainer();
jetzt kann ich Tokens erstellen, aber diese werden sofort immer als falsch identifiziert.
ich gehe folgenden Weg:
User - my account - access tokenmeine Portainer Vers: Community Edition 2.33.0.LTS
-
ja da hat sich die ki verschwurbelt
hier eine neue skript version. diesmal habe ich sie selbst ausprobiert
ich habe mal meine daten drin gelassen, damit du ein gefühl bekommst was da drin stehen könnte.
das login wurde nun auf userid/passwort umgestellt.
die endpoint id lass bitte auf 1, entweder ist das die api version oder die environment id, da du wahrscheinlich nur ein system mit portainer administriest, wird das auch bei dir 1 sein.// Nur Node http Modul, ganz einfach const http = require('http'); // Konfiguration: const PORTAINER_HOST = '192.168.1.40'; const PORTAINER_PORT = 9100; const PORTAINER_USERNAME = 'admin'; const PORTAINER_PASSWORD = 'adminadmin'; const PORTAINER_ENDPOINT_ID = '1'; const PORTAINER_CONTAINER_ID = '681ada44f1d73fcc8645c8b623d7f724e860632ca9bc6bbb9e9bf1f06451e32d'; const PORTAINER_RESTART_TIMEOUT = '10'; function httpRequest(path, method, headers, body, callback) { const options = { hostname: PORTAINER_HOST, port: PORTAINER_PORT, path, method, headers, }; const req = http.request(options, (res) => { let data = ''; res.on('data', (chunk) => (data += chunk)); res.on('end', () => { callback(null, { statusCode: res.statusCode, body: data }); }); }); req.on('error', (err) => callback(err)); if (body) req.write(body); req.end(); } function loginAndGetJWT(cb) { const body = JSON.stringify({ Username: PORTAINER_USERNAME, Password: PORTAINER_PASSWORD }); httpRequest( '/api/auth', 'POST', { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), }, body, (err, res) => { if (err) return cb(err); if (res.statusCode !== 200) return cb(new Error('Login fehlgeschlagen: ' + res.body)); let data; try { data = JSON.parse(res.body); } catch (e) { return cb(e); } if (!data.jwt) return cb(new Error('Kein JWT im Response.')); cb(null, data.jwt); } ); } function restartContainer(jwt, cb) { const path = `/api/endpoints/${PORTAINER_ENDPOINT_ID}/docker/containers/${PORTAINER_CONTAINER_ID}/restart` + `?t=${PORTAINER_RESTART_TIMEOUT}`; httpRequest( path, 'POST', { Authorization: 'Bearer ' + jwt }, null, (err, res) => { if (err) return cb(err); if (res.statusCode !== 204) return cb(new Error('Restart fehlgeschlagen: ' + res.body)); cb(null); } ); } // Ablauf: loginAndGetJWT((err, jwt) => { if (err) return console.error('Login Fehler:', err.message); restartContainer(jwt, (err2) => { if (err2) return console.error('Restart Fehler:', err2.message); console.log(`✅ Container ${PORTAINER_CONTAINER_ID} neu gestartet.`); }); });
-
@oliverio Danke, jetzt hab ich es hin bekommen, obwohl es erst funktioniert hat, als ich als EndpointId 3 eingegeben hatte.