Hallo zusammen,
nachdem ich mich etwas intensiver mit Docker auseinandergesetzt habe, konnte ich endlich einige Raspberry abschaffen, die hier im Haushalt für das eine oder andere zuständig waren. Im Einzelnen lasse ich zwei PiHole laufen. Einen für die Kids, auf dem die google und youtube safesearch aktiviert ist und einen normalen für die restlichen Haushaltsmitglieder. Zudem habe ich noch influxDB, ioBroker und grafana laufen, um Sensor-Daten aus meiner Hausautomation (Loxone) zu speichern. Sowie ecoDMS, aber das benutze ich noch nicht live.
Jetzt hatte ich mir Portainer angeschaut, um die Unzulänglichkeiten der Synology Oberfläche auszumerzen sowie Watchtower zum automatisierten Update der Container. Am Ende fand ich das alles nicht zufriedenstellend. Zu viel, am Ende muss man eben doch genau wissen, was man tut und so habe ich mich entschieden, etwas näher docker-compose anzuschauen.
Am Ende muss ich sagen, korrekte Entscheidung:
Vorbereitung - Ein eigener IP-Bereich für Container:
Einige meiner Container sollen mit einer eigenen IP laufen. Das betrifft natürlich insbesondere die beiden PiHole. Hierfür bedarf es als Voraussetzung den macvlan Treiber. Prinzipiell kann man das Netzwerk auch über die docker-compose.yml anlegen, aber ich hatte mich dazu entschieden, dieses Netzwerk einmal aufzusetzen und es dann zu verwenden, ohne dass es laufend durch docker-compose Befehlen zu Wechselwirkungen kommt.
Ich habe hierzu einen Adressbereich in meinem Router so eingestellt, dass diese Adressen nicht durch DHCP vergeben werden und somit exklusiv vergeben werden können.
Um nun ein macvlan namens „VLAN“ für die Container zur Verfügung zu stellen, brauchen wir den folgenden Befehl. Hierbei ist zu beachten, dass eure physische LAN Schnittstelle verwendet werden muss, d.h. im Standardfall eth0, wollt ihr es auf dem zweiten LAN Anschluss laufen lassen eth1, wenn ihr virtuelle Maschinen laufen lasst, wird es ovs_eth0 oder ovs_eth1 sein. Wir setzen den folgenden Befehl ab, um dem macvlan die IP Adressen *.192 bis *.254 zuzuweisen.
Um Beispielsweise ein Netzwerk mit einer einzelnen IP Adresse zu erstellen, würde man die IP Range mit folgendem ersetzen:
hat dann aber auch nur eine zur Verfügung. Wenn man nur einen Container hat, der eine eigene IP bekommen soll, ist das ein galanter Weg, denn dann kann man die Verwaltung über die GUI der Synology vornehmen. Startet man einen Container in dem macvlan, wird dieser direkt mit der einzigen verfügbaren IP gestartet.
Die Notation erfolgt als CIDR. Einfach nach CIDR Rechner googeln. Da findet sich zumeist was.
Das Netzwerk wieder löschen, könnt ihr mit folgendem Befehl, allerdings darf dann kein Container mehr damit verbunden sein:
Das docker-compose.yml file:
Der aufwändigste Teil ist die Erstellung des docker-compose.yml files, denn hier muss jeder eurer Container rein. Allerdings werde ich die Fallstricke, an denen ich eine gefühlte Ewigkeit gehangen habe, hier andiskutieren (Einbinden externer Netzwerke und Vergabe von IP Adressen für die Container).
Wenn ihr ein Docker image verwenden wollt, gibt es üblicherweise auf der Seite des Bereitstellers auch Informationen, wie das file aufgebaut sein muss bzw. welche Variablen Ordner-Verknüpfungen ihr benötigt. Wichtig ist, dass ihr den Dateiaufbau einhaltet und alle Einrückungen entsprechend vornehmt. Prüfen könnt ihr eure erstellte yml Datei mit folgendem Befehl:
Um mich nicht in Details zu verlieren, findet ihr hier mein Beispiel einer solchen Datei:
(Achtung, das Forum schluckt die Formatierung...)
Was ist hierbei wichtig: Das von uns erstellte Netzwerk namens VLAN muss als extern eingebunden werden, damit docker es kennt und die Container darauf starten kann. Über docker-compose sollten letztlich alle eure Container eingebunden werden, nur dann macht das ganze Sinn.
Ihr könnt für jeden eurer Container die Umgebungsvariablen setzen, die ihr benötigt und auch eure persistenten Verzeichnisse mappen.
Für die PiHoles ist in der Datei eine eigene IP zugewiesen, sowie die macAdresse. Letzteres ist m.E. nicht zwingend notwendig. Die mac Adressen der Container beginnen immer mit: 02:42:C0:A8:02:XX Die Zahlen dahinter im Hex-Format ersetzen. (Bei eigener IP entfällt das ganze Portmapping im Docker.)
Ich habe mein docker compose file in meinen Docker-Ordner /volume1/docker/ gelegt und arbeite dann auch aus diesem Ordner heraus, wenn es mich mal wieder auf die Terminaloberfläche verschlägt.
Hier ein paar wichtige Befehle, die ihr über den Terminal absetzen könnt:
Nachdem ihr das Docker File erstellt und alle eure Container auf der GUI gelöscht habt, könnt ihr mit
die Services starten. Diese tauchen dann auch wieder in der GUI der Synology auf.
Händisches Updaten ist Vergangenheit:
Mich hat das händische updaten genervt. Daher habe ich im Internet gesucht und vieles gefunden, aber alles irgendwie halbgar. Also, meine alten Scripting Kenntnisse zusammengesammelt und mir hier und da ein paar Code-Schnipsel und Anregungen besorgt. Dabei ist folgendes Script entstanden, dass prüft, ob es ein neues Image für laufende Services gibt, dies herunterlädt, den Container löscht, auf Basis des neuen Images aufbaut und wieder startet. Das Script liegt bei mir ebenfalls im docker Ordner.
Starten könnt ihr das Script einfach über die Terminaloberfläche (als root) mit:
Ihr bekommt entsprechende Rückmeldung über die Shell. Möchtet ihr noch ein Logfile erstellen, nutzt den Parameter -v beim Aufruf.
Sinn macht das ganze aber insbesondere nur, wenn ihr das über den Synology Aufgabenplaner ausführt. Hierzu im entsprechenden Feld in der Synology GUI folgendes eingeben:
Der Parameter -q erzeugt immer das logfile im Ordner in dem auch das Script und das .yml file liegt. Leider habe ich es nicht geschafft, das Log automatisch per Mail zu versenden. Es existiert immer nur die Log-Datei der letzten Ausführung im Ordner, in den man dann eben schauen muss. Hier mal ein Beispiel indem auch der grafana Container geupdated wurde:
Es gibt leider noch ein paar komische Sonderzeichen im log. Die werden durch die docker Routine zurückgegeben. Da hatte ich noch keine Muße zu, das zu beheben.
Falls ihr Rückfragen oder Anregungen habt, könnt ihr gerne Fragen stellen. Ich bemühe mich, diese zu beantworten und Bugs zu beseitigen.
Für mich offen ist insbesondere, wie ich dem Aufgabenplaner die log Daten mitgebe, um diese dann automatisch per Mail zu erhalten. Das wäre toll.
Viele Grüße und vielen Dank für die Hilfe, die ich hier auch als stiller Mitleser immer bekomme.[/SPOILER][/SPOILER]
nachdem ich mich etwas intensiver mit Docker auseinandergesetzt habe, konnte ich endlich einige Raspberry abschaffen, die hier im Haushalt für das eine oder andere zuständig waren. Im Einzelnen lasse ich zwei PiHole laufen. Einen für die Kids, auf dem die google und youtube safesearch aktiviert ist und einen normalen für die restlichen Haushaltsmitglieder. Zudem habe ich noch influxDB, ioBroker und grafana laufen, um Sensor-Daten aus meiner Hausautomation (Loxone) zu speichern. Sowie ecoDMS, aber das benutze ich noch nicht live.
Jetzt hatte ich mir Portainer angeschaut, um die Unzulänglichkeiten der Synology Oberfläche auszumerzen sowie Watchtower zum automatisierten Update der Container. Am Ende fand ich das alles nicht zufriedenstellend. Zu viel, am Ende muss man eben doch genau wissen, was man tut und so habe ich mich entschieden, etwas näher docker-compose anzuschauen.
Am Ende muss ich sagen, korrekte Entscheidung:
- Ich weiß genau, was die Container brauchen.
- Ich habe es einmal in der docker-compose.yml für jeden Service, den ich benötige eingestellt und kann jederzeit Container löschen und anlegen ohne diese nervige rumgeklicke und neu eintragen von irgendwelchen Pfaden und Portmappings.
- Ich kann Dinge in der docker-compose beeinflussen, die über die Weboberfläche der Synology nicht möglich sind. (z.B. IP Adressen für den Container zuweisen.)
- Man kann nun wunderbar mit einem Script einzelne Docker-Images updaten und die Services (Container) auch einzeln updaten. Alle Scripts, die ich in den Weiten des Netzes fand, haben letztlich immer alle Container gestoppt, gelöscht und wieder neu angelegt und gestartet. Aber warum sollte der PiHole neu aufgesetzt werden, wenn grafana ein Update erhält?! Also habe ich ein eigenes Script geschrieben,
- Zugang per Terminal auf eure Synology
- Ein docker-compose.yml file, dass alle Parameter für eure Services enthält. (Beispiel folgt)
- ein paar notwendige Grundbefehle
- Gewisse Kenntnisse über macvlan
- das Updatescript (folgt)
- Einstellung im Aufgabenplaner
Vorbereitung - Ein eigener IP-Bereich für Container:
Einige meiner Container sollen mit einer eigenen IP laufen. Das betrifft natürlich insbesondere die beiden PiHole. Hierfür bedarf es als Voraussetzung den macvlan Treiber. Prinzipiell kann man das Netzwerk auch über die docker-compose.yml anlegen, aber ich hatte mich dazu entschieden, dieses Netzwerk einmal aufzusetzen und es dann zu verwenden, ohne dass es laufend durch docker-compose Befehlen zu Wechselwirkungen kommt.
Ich habe hierzu einen Adressbereich in meinem Router so eingestellt, dass diese Adressen nicht durch DHCP vergeben werden und somit exklusiv vergeben werden können.
Um nun ein macvlan namens „VLAN“ für die Container zur Verfügung zu stellen, brauchen wir den folgenden Befehl. Hierbei ist zu beachten, dass eure physische LAN Schnittstelle verwendet werden muss, d.h. im Standardfall eth0, wollt ihr es auf dem zweiten LAN Anschluss laufen lassen eth1, wenn ihr virtuelle Maschinen laufen lasst, wird es ovs_eth0 oder ovs_eth1 sein. Wir setzen den folgenden Befehl ab, um dem macvlan die IP Adressen *.192 bis *.254 zuzuweisen.
Code:
sudo docker network create -d macvlan --subnet=192.168.2.0/24 --gateway=192.168.2.1 --ip-range=192.168.2.192/26 -o parent=ovs_eth1 VLAN
Um Beispielsweise ein Netzwerk mit einer einzelnen IP Adresse zu erstellen, würde man die IP Range mit folgendem ersetzen:
Code:
--ip-range=192.168.2.192/32
Die Notation erfolgt als CIDR. Einfach nach CIDR Rechner googeln. Da findet sich zumeist was.
Das Netzwerk wieder löschen, könnt ihr mit folgendem Befehl, allerdings darf dann kein Container mehr damit verbunden sein:
Code:
sudo docker network rm VLAN
Das docker-compose.yml file:
Der aufwändigste Teil ist die Erstellung des docker-compose.yml files, denn hier muss jeder eurer Container rein. Allerdings werde ich die Fallstricke, an denen ich eine gefühlte Ewigkeit gehangen habe, hier andiskutieren (Einbinden externer Netzwerke und Vergabe von IP Adressen für die Container).
Wenn ihr ein Docker image verwenden wollt, gibt es üblicherweise auf der Seite des Bereitstellers auch Informationen, wie das file aufgebaut sein muss bzw. welche Variablen Ordner-Verknüpfungen ihr benötigt. Wichtig ist, dass ihr den Dateiaufbau einhaltet und alle Einrückungen entsprechend vornehmt. Prüfen könnt ihr eure erstellte yml Datei mit folgendem Befehl:
Code:
docker-compose -f docker-compose.yml config
Um mich nicht in Details zu verlieren, findet ihr hier mein Beispiel einer solchen Datei:
(Achtung, das Forum schluckt die Formatierung...)
Code:
version: "3"
services:
#PiHole
pihole:
container_name: PiHole
image: pihole/pihole:latest
hostname: PiHole
environment:
TZ: 'Europe/Berlin'
WEBPASSWORD: 'YOURSAFEPASSWORD'
volumes:
- '/volume1/docker/pihole/:/etc/pihole/'
- '/volume1/docker/pihole/dnsmasq.d/:/etc/dnsmasq.d/'
cap_add:
- NET_ADMIN
restart: always
mac_address: 02:42:C0:A8:02:XX
networks:
VLAN:
ipv4_address: XXX.XXX.XXX.XXX
#PiHole_Kids
pihole_kids:
container_name: PiHole_Kids
image: pihole/pihole:latest
hostname: PiHole-Kids
environment:
TZ: 'Europe/Berlin'
WEBPASSWORD: 'YOURSAFEPASSWORD'
volumes:
- '/volume1/docker/pihole_kids/:/etc/pihole/'
- '/volume1/docker/pihole_kids/dnsmasq.d/:/etc/dnsmasq.d/'
cap_add:
- NET_ADMIN
restart: always
mac_address: 02:42:C0:A8:02:YY
networks:
VLAN:
ipv4_address: XXX.XXX.XXX.YYY
#ioBroker
ioBroker:
container_name: ioBroker
image: buanet/iobroker:latest-v5
hostname: ioBroker
ports:
- "8081:8081"
environment:
TZ: 'Europe/Berlin'
volumes:
- '/volume1/docker/iobroker/:/opt/iobroker/'
restart: always
network_mode: bridge
#influxDB
influxDB:
container_name: influxDB
image: influxdb:latest
hostname: influxDB
ports:
- "8086:8086"
environment:
TZ: 'Europe/Berlin'
INFLUXDB_ADMIN_PASSWORD: YOURSAFEPASSWORDHERE
INFLUXDB_USER: admin
volumes:
- '/volume1/docker/influxDB/:/var/lib/influxdb/'
restart: always
network_mode: bridge
#grafana
grafana:
container_name: grafana
image: grafana/grafana:latest
hostname: grafana
ports:
- "3000:3000"
volumes:
- '/volume1/docker/grafana/:/var/lib/grafana/'
restart: always
network_mode: bridge
#ecoDMS
ecoDMS:
container_name: ecoDMS
image: ecodms/allinone-18.09:latest
hostname: ecoDMS
ports:
- "17001:17001/tcp"
- "17002:17002/tcp"
- "17004:8080/tcp"
- "17005:8180/tcp"
volumes:
- '/volume1/docker/ecoDMS/restore/:/srv/restore/'
- '/volume1/docker/ecoDMS/scaninput/:/srv/scaninput/'
- '/volume1/docker/ecoDMS/backup/:/srv/backup/'
- '/volume1/docker/ecoDMS/data/:/srv/data/'
restart: always
network_mode: bridge
#Bekanntmachung des bereits eingerichteten macVLANs
networks:
VLAN:
external: true
Was ist hierbei wichtig: Das von uns erstellte Netzwerk namens VLAN muss als extern eingebunden werden, damit docker es kennt und die Container darauf starten kann. Über docker-compose sollten letztlich alle eure Container eingebunden werden, nur dann macht das ganze Sinn.
Ihr könnt für jeden eurer Container die Umgebungsvariablen setzen, die ihr benötigt und auch eure persistenten Verzeichnisse mappen.
Für die PiHoles ist in der Datei eine eigene IP zugewiesen, sowie die macAdresse. Letzteres ist m.E. nicht zwingend notwendig. Die mac Adressen der Container beginnen immer mit: 02:42:C0:A8:02:XX Die Zahlen dahinter im Hex-Format ersetzen. (Bei eigener IP entfällt das ganze Portmapping im Docker.)
Ich habe mein docker compose file in meinen Docker-Ordner /volume1/docker/ gelegt und arbeite dann auch aus diesem Ordner heraus, wenn es mich mal wieder auf die Terminaloberfläche verschlägt.
Hier ein paar wichtige Befehle, die ihr über den Terminal absetzen könnt:
Code:
#starten der docker muss aus Verzeichnis docker erfolgen
sudo docker-compose up -d
#alle Container aktualisieren
sudo docker-compose pull
#Löschen aller Docker inklusive aller nicht externen Netzwerke
sudo docker-compose down
#Prüfung des docker-compose.yml files auf Fehler
docker-compose -f docker-compose.yml config
#Schauen, welche Container es gibt
sudo docker ps
#Container starten
sudo docker stop <ID, z.B.: fd132a7f9490>
#Container Löschen
sudo docker rm <ID, z.B.: fd132a7f9490>
#Docker Infos
sudo docker info
#Docker Hilfe
docker-compose help
Nachdem ihr das Docker File erstellt und alle eure Container auf der GUI gelöscht habt, könnt ihr mit
Code:
sudo docker-compose up -d
Händisches Updaten ist Vergangenheit:
Mich hat das händische updaten genervt. Daher habe ich im Internet gesucht und vieles gefunden, aber alles irgendwie halbgar. Also, meine alten Scripting Kenntnisse zusammengesammelt und mir hier und da ein paar Code-Schnipsel und Anregungen besorgt. Dabei ist folgendes Script entstanden, dass prüft, ob es ein neues Image für laufende Services gibt, dies herunterlädt, den Container löscht, auf Basis des neuen Images aufbaut und wieder startet. Das Script liegt bei mir ebenfalls im docker Ordner.
Code:
#!/bin/bash
set -o errexit
DOCKER_PATH="/volume1/docker/"
LOG_FILE="docker-compose-update.log"
cd $DOCKER_PATH
#check if quiet or verbose mode option is set, mandatory when using the Synology scheduler
#call script with -q in Synology scheduler!
#For direct shell usage and output on shell and log call with -v
#processing command line options
while getopts qv opt
do
case $opt in
q) exec > $LOG_FILE 2>&1;; #quiet mode, feedback only written to log
v) exec > >(/bin/tee $LOG_FILE) 2>&1;; #split up echo of script to terminal and log
#no argument only feedback in shell
esac
done
#unset script command line options
set --
# Get the Container IDs as List
CONTAINER_LIST="${1:-$(docker ps -q)}"
echo "Starting Update procedure for containers at" $(date +%c)
for CONTAINER_ID in ${CONTAINER_LIST}; do
#Get the container image name, get the hash of the running image, get the service name like in docker-compose.yml
CONTAINER_IMAGE="$(docker inspect --format "{{.Config.Image}}" --type container ${CONTAINER_ID})"
RUNNING_IMAGE="$(docker inspect --format "{{.Image}}" --type container "${CONTAINER_ID}")"
SERVICE_NAME="$(docker inspect --format "{{index .Config.Labels \"com.docker.compose.service\"}}" --type container ${CONTAINER_ID})"
echo -e "\n------------------------------------------------- "$SERVICE_NAME" ------------------------------------------------------"
echo "Checking" $SERVICE_NAME" @ "$CONTAINER_IMAGE
#Pull the latest image and get the hash
docker pull $CONTAINER_IMAGE
LATEST_IMAGE="$(docker inspect --format "{{.Id}}" --type image "$CONTAINER_IMAGE")"
#if hash of runming image is not equal to hash of latest image forcing an update
if [[ "$RUNNING_IMAGE" != "$LATEST_IMAGE" ]]; then
echo "Status: Image of the running service is not up to date."
echo -e "\nTry to stop and remove Service " $SERVICE_NAME" @ Container "${CONTAINER_ID}
docker-compose rm -f -s $SERVICE_NAME
echo -e "\nTry to build and start Service " $SERVICE_NAME
docker-compose up -d --build $SERVICE_NAME
else
echo -e "\nStatus: Image of the running service is up to date."
fi
done
echo -e "\n------------------------------------------------- Finished at" $(date +%c)"! -------------------------------"
Starten könnt ihr das Script einfach über die Terminaloberfläche (als root) mit:
Code:
/volume1/docker/docker-compose-update-script.sh
Ihr bekommt entsprechende Rückmeldung über die Shell. Möchtet ihr noch ein Logfile erstellen, nutzt den Parameter -v beim Aufruf.
Sinn macht das ganze aber insbesondere nur, wenn ihr das über den Synology Aufgabenplaner ausführt. Hierzu im entsprechenden Feld in der Synology GUI folgendes eingeben:
Der Parameter -q erzeugt immer das logfile im Ordner in dem auch das Script und das .yml file liegt. Leider habe ich es nicht geschafft, das Log automatisch per Mail zu versenden. Es existiert immer nur die Log-Datei der letzten Ausführung im Ordner, in den man dann eben schauen muss. Hier mal ein Beispiel indem auch der grafana Container geupdated wurde:
Code:
Starting Update procedure for containers at Sat 06 Feb 2021 02:01:55 PM CET
------------------------------------------------- grafana ------------------------------------------------------
Checking grafana @ grafana/grafana:latest
latest: Pulling from grafana/grafana
Digest: sha256:5d54d8c09218f7cf8bd81a1e6904c4fd600f63178d54cbae4445a8155d408c8a
Status: Image is up to date for grafana/grafana:latest
Status: Image of the running service is up to date.
------------------------------------------------- influxDB ------------------------------------------------------
Checking influxDB @ influxdb:latest
latest: Pulling from library/influxdb
2587235a7635: Already exists
d4ae0ade1586: Pulling fs layer
911674ee9a54: Pulling fs layer
90fc1901fc42: Pulling fs layer
e451b666a9d4: Pulling fs layer
f404a52d19aa: Pulling fs layer
a9c378eb5166: Pulling fs layer
2b9f747a0a1e: Pulling fs layer
e451b666a9d4: Waiting
f404a52d19aa: Waiting
a9c378eb5166: Waiting
2b9f747a0a1e: Waiting
90fc1901fc42: Verifying Checksum
911674ee9a54: Verifying Checksum
911674ee9a54: Download complete
f404a52d19aa: Verifying Checksum
f404a52d19aa: Download complete
d4ae0ade1586: Verifying Checksum
d4ae0ade1586: Download complete
a9c378eb5166: Verifying Checksum
a9c378eb5166: Download complete
2b9f747a0a1e: Verifying Checksum
2b9f747a0a1e: Download complete
d4ae0ade1586: Pull complete
911674ee9a54: Pull complete
90fc1901fc42: Pull complete
e451b666a9d4: Verifying Checksum
e451b666a9d4: Download complete
e451b666a9d4: Pull complete
f404a52d19aa: Pull complete
a9c378eb5166: Pull complete
2b9f747a0a1e: Pull complete
Digest: sha256:f509fe90d586ce80a6951059d380ebcad54a790285a630c4d77472287a230c17
Status: Downloaded newer image for influxdb:latest
Status: Image of the running service is not up to date.
Try to stop and remove Service influxDB @ Container 8c98dca5b699
Stopping influxDB ...
[1A[2K
Stopping influxDB ... [32mdone[0m
[1BRemoving influxDB ...
[1A[2K
Removing influxDB ... [32mdone[0m
[1BGoing to remove influxDB
Try to build and start Service influxDB
Creating influxDB ...
[1A[2K
Creating influxDB ... [32mdone[0m
[1B
------------------------------------------------- ioBroker ------------------------------------------------------
Checking ioBroker @ buanet/iobroker:latest-v5
latest-v5: Pulling from buanet/iobroker
Digest: sha256:810f20945a0a2d64bacdbdac669821f29071512cb77f5b63d9d123664cbf7c9b
Status: Image is up to date for buanet/iobroker:latest-v5
Status: Image of the running service is up to date.
------------------------------------------------- pihole ------------------------------------------------------
Checking pihole @ pihole/pihole:latest
latest: Pulling from pihole/pihole
Digest: sha256:6a633b5b2b4a9f343aa01101c89ebba36aa90003df0e379d2e702e0372ed9712
Status: Image is up to date for pihole/pihole:latest
Status: Image of the running service is up to date.
------------------------------------------------- pihole_kids ------------------------------------------------------
Checking pihole_kids @ pihole/pihole:latest
latest: Pulling from pihole/pihole
Digest: sha256:6a633b5b2b4a9f343aa01101c89ebba36aa90003df0e379d2e702e0372ed9712
Status: Image is up to date for pihole/pihole:latest
Status: Image of the running service is up to date.
------------------------------------------------- Finished at Sat 06 Feb 2021 02:02:27 PM CET! -----------------------
Es gibt leider noch ein paar komische Sonderzeichen im log. Die werden durch die docker Routine zurückgegeben. Da hatte ich noch keine Muße zu, das zu beheben.
Falls ihr Rückfragen oder Anregungen habt, könnt ihr gerne Fragen stellen. Ich bemühe mich, diese zu beantworten und Bugs zu beseitigen.
Für mich offen ist insbesondere, wie ich dem Aufgabenplaner die log Daten mitgebe, um diese dann automatisch per Mail zu erhalten. Das wäre toll.
Viele Grüße und vielen Dank für die Hilfe, die ich hier auch als stiller Mitleser immer bekomme.[/SPOILER][/SPOILER]
Zuletzt bearbeitet: