Hi,
um das Script auch im ContainerManager/Docker auf einer Synology zum laufen zu bringen benötigt man Zugriff auf
'/var/run/docker.sock'
Vielleicht geht es wenn man Symcon privilegiert startet oder die erweiterten Möglichkeiten des ContainerManagers benutzt. Ich habe einen anderen Weg gewählt. Ich biege docker.sock auf einen normalen TCP-Port um. Vorteil 1 es arbeitet auch in nichtprivilegierten Images und Vorteil 2 man kann Docker auch von anderen Rechnern steuern. Wenn man mutig ist auch per Freigabe aus dem Internet.
Um den docker.sock umzubiegen benötigt man zuerst einen SSH Zugang zur Synology. Man logged sich ein und dann
cd /
sudo find -name dockerd.json
Bei mir befindet sich die Datei in /volume1/@appconf/ContainerManager/dockerd.json. Diese Datei kopiert man in eine Freigabe auf der Synology mit
sudo cp /volume1/@appconf/ContainerManager/dockerd.json /volume1/public/
Diese Datei sieht bei mir so aus
{"data-root":"/var/packages/ContainerManager/var/docker","log-driver":"db","registry-mirrors":[],"storage-driver":"btrfs"}
und ist ein json String.
In diesen String muss
"hosts":["tcp://192.168.178.2:2375","unix:///var/run/docker.sock"],
hinzugefügt werden damit docker.sock uf einen TCP Port umgeleitet wird. Der String muss dann in etwa so aussehen
{"data-root":"/var/packages/ContainerManager/var/docker","hosts":["tcp://192.168.178.2:2375","unix:///var/run/docker.sock"],"log-driver":"db","registry-mirrors":[],"storage-driver":"btrfs"}
192.168.178.2 ist meine Synology und 2375 ist der Port den ich gewählt habe. Diese Datei muss man dann wieder zurück kopieren mit
sudo cp /volume1/public/dockerd.json /volume1/@appconf/ContainerManager/
Nachdem man den Containermanager neu gestartet hat sollte die Steuerung von docker über 192.168.178.2:2375 gehen und kann im eigenen Netz von jedem Rechner gemacht werden. Das Script von BlackOrca muss an 2 Stellen angepasst werden damit es funktioniert. Hier mein geändertes Script das zusätzlich auch noch den Speicher und die IDs der Container ausliest. Mit der ID lassen sich so schöne Sachen wie Start/Stop machen. Dank des sehr übersichtlich geschriebenen Original Scripts ist eine Erweiterung ein Klacks. Danke dafür Dennis.
<?php
$DummyInstanceId = "{485D0419-BE97-4548-AA9C-C083EB82E61E}";
$ParentFolder = 35944;
$client = new DockerClient('http://192.168.178.2:2375');
//$dockerContainers = $client->dispatchCommand('/containers/json?all=1&size=1');
$dockerContainers = $client->dispatchCommand('/containers/json?size=1');
var_dump($dockerContainers);
foreach ($dockerContainers as $container)
{
$instanceId = AddOrUpdateContainerInfos($container);
$containerDetails = $client->dispatchCommand('/containers/'.$container['Id'].'/json');
AddOrUpdateContainerDetails($instanceId, $containerDetails);
}
$dockerInfo = $client->dispatchCommand('/info');
if($dockerInfo === false) return;
AddOrUpdateDockerInfo("Container gesamt", VARIABLETYPE_INTEGER, $ParentFolder, $dockerInfo['Containers']);
AddOrUpdateDockerInfo("Container werden Ausgeführt", VARIABLETYPE_INTEGER, $ParentFolder, $dockerInfo['ContainersRunning']);
AddOrUpdateDockerInfo("Container die Pausiert sind", VARIABLETYPE_INTEGER, $ParentFolder, $dockerInfo['ContainersPaused']);
AddOrUpdateDockerInfo("Container die Gestoppt sind", VARIABLETYPE_INTEGER, $ParentFolder, $dockerInfo['ContainersStopped']);
AddOrUpdateDockerInfo("Vorhandene Images", VARIABLETYPE_INTEGER, $ParentFolder, $dockerInfo['Images']);
AddOrUpdateDockerInfo("Kernel Version", VARIABLETYPE_STRING, $ParentFolder, $dockerInfo['KernelVersion']);
AddOrUpdateDockerInfo("Betriebssystem", VARIABLETYPE_STRING, $ParentFolder, $dockerInfo['OperatingSystem']);
AddOrUpdateDockerInfo("Betriebsystem Version", VARIABLETYPE_STRING, $ParentFolder, $dockerInfo['OSVersion']);
AddOrUpdateDockerInfo("Docker Version", VARIABLETYPE_STRING, $ParentFolder, $dockerInfo['ServerVersion']);
$Children = IPS_GetChildrenIDs($ParentFolder);
foreach ($Children as $Child) {
DockerCheck($Child);
}
/* Functions */
function DockerCheck($ParentID){
$Object = IPS_GetObject($ParentID);
if ($Object['ObjectType'] != 1) return;
$StatusID = IPS_GetObjectIDByName('Status', $ParentID);
$Variable = IPS_GetVariable($StatusID);
if ((time() - $Variable['VariableUpdated']) > 86400){
$Children = IPS_GetChildrenIDs($ParentID);
foreach ($Children as $Child) {
IPS_DeleteVariable($Child);
}
IPS_DeleteInstance($ParentID);
}
}
function AddOrUpdateContainerDetails($instanceId, $containerDetails)
{
AddOrUpdateRestartCount($instanceId, $containerDetails);
}
function AddOrUpdateContainerInfos($container)
{
$instanceId = AddOrUpdateInstance($container);
//var_dump($container);
AddOrUpdateCreated($instanceId, $container);
AddOrUpdateState($instanceId, $container);
AddOrUpdateStatus($instanceId, $container);
AddOrUpdateImage($instanceId, $container);
AddOrUpdateSizeRootFs ($instanceId, $container);
AddOrUpdateSizeRw($instanceId, $container);
AddOrUpdateSizeId($instanceId, $container);
return $instanceId;
}
function AddOrUpdateDockerInfo($propertyName, $type, $parentId, $value)
{
$propertyId = @IPS_GetVariableIDByName($propertyName, $parentId);
if($propertyId === false)
{
$propertyId = IPS_CreateVariable($type);
IPS_SetName($propertyId, $propertyName);
IPS_SetParent($propertyId, $parentId);
}
$oldValue = GetValue($propertyId);
if($oldValue != $value)
SetValue($propertyId, $value);
}
function AddOrUpdateRestartCount($instanceId, $containerDetails)
{
AddOrUpdate($instanceId, $containerDetails, "Neustarts", VARIABLETYPE_INTEGER, "", $containerDetails['RestartCount']);
}
function AddOrUpdateImage($instanceId, $container)
{
AddOrUpdate($instanceId, $container, "Container Image", VARIABLETYPE_STRING, "", $container['Image']);
}
function AddOrUpdateStatus($instanceId, $container)
{
AddOrUpdate($instanceId, $container, "Status", VARIABLETYPE_STRING, "", $container['Status']);
}
function AddOrUpdateState($instanceId, $container)
{
AddOrUpdate($instanceId, $container, "Ausführung", VARIABLETYPE_STRING, "", $container['State']);
}
function AddOrUpdateCreated($instanceId, $container)
{
AddOrUpdate($instanceId, $container, "Erstellt", VARIABLETYPE_INTEGER, "~UnixTimestamp", $container['Created']);
}
function AddOrUpdateSizeRw($instanceId, $container)
{
if (isset($container['SizeRw']))AddOrUpdate($instanceId, $container, "verändert", VARIABLETYPE_FLOAT, "MByte", floatval($container['SizeRw']) / 1048576);
}
function AddOrUpdateSizeRootFs ($instanceId, $container)
{
AddOrUpdate($instanceId, $container, "Größe", VARIABLETYPE_FLOAT, "MByte", floatval($container['SizeRootFs']) / 1048576);
}
function AddOrUpdateSizeId ($instanceId, $container)
{
AddOrUpdate($instanceId, $container, "ID", VARIABLETYPE_STRING, "", $container['Id']);
}
function AddOrUpdate($instanceId, $container, $varName, $varType, $varProfile, $arrayProperty)
{
$createdId = @IPS_GetVariableIDByName($varName, $instanceId);
if($createdId === false)
{
$createdId = IPS_CreateVariable($varType);
IPS_SetParent($createdId, $instanceId);
IPS_SetName($createdId, $varName);
IPS_SetVariableCustomProfile($createdId, $varProfile);
}
if(GetValue($createdId) != $arrayProperty)
{
SetValue($createdId, $arrayProperty);
}
}
function GetName($container)
{
return substr($container['Names'][0], 1);
}
function AddOrUpdateInstance($container)
{
global $ParentFolder;
global $DummyInstanceId;
$containerName = GetName($container);
$instanceId = @IPS_GetInstanceIDByName($containerName, $ParentFolder);
if($instanceId === false)
{
$instanceId = IPS_CreateInstance($DummyInstanceId);
IPS_SetParent($instanceId, $ParentFolder);
IPS_SetName($instanceId, $containerName);
}
return $instanceId;
}
/*Credits https://gist.github.com/FergusInLondon/c3eb96f1f6565a81e509ece6b14b9a78 */
class DockerClient {
/** @param resource */
private $curlClient;
/** @param string */
private $socketPath;
/** @param string|null */
private $curlError = null;
/**
* Constructor: Initialises the Curl Resource, making it usable for subsequent
* API requests.
*
* @param string
*/
public function __construct(string $socketPath)
{
$this->curlClient = curl_init();
$this->socketPath = $socketPath;
curl_setopt($this->curlClient, CURLOPT_PORT, 2375);
curl_setopt($this->curlClient, CURLOPT_RETURNTRANSFER, true);
}
/**
* Deconstructor: Ensure the Curl Resource is correctly closed.
*/
public function __destruct()
{
curl_close($this->curlClient);
}
private function generateRequestUri(string $requestPath)
{
/* Please note that Curl doesn't use http+unix:// or any other mechanism for
* specifying Unix Sockets; once the CURLOPT_UNIX_SOCKET_PATH option is set,
* Curl will simply ignore the domain of the request. Hence why this works,
* despite looking as though it should attempt to connect to a host found at
* the domain "unixsocket". See L14 where this is set.
*
* @see Client.php:L14
* @see https://github.com/curl/curl/issues/1338
*/
return sprintf("http://192.168.178.2:2375%s", $requestPath);
}
/**
* Dispatches a command - via Curl - to Commander's Unix Socket.
*
* @param string Docker Engine endpoint to hit.
* @param array Data to post to $endpoint.
* @return array JSON decoded response from Commander.
*/
public function dispatchCommand(string $endpoint, array $parameters = null): array
{
curl_setopt($this->curlClient, CURLOPT_URL, $this->generateRequestUri($endpoint));
if (!is_null($parameters)) {
$payload = json_encode($parameters);
curl_setopt($this->curlClient, CURLOPT_POSTFIELDS, $payload);
}
$result = curl_exec($this->curlClient);
if ($result === FALSE) {
$this->curlError = curl_error($this->curlClient);
return array();
}
return json_decode($result, true);
}
/**
* Returns a human readable string from Curl in the event of an error.
*
* @return bool|string
*/
public function getCurlError()
{
return is_null($this->curlError) ? false : $this->curlError;
}
}
Ralf