Inhaltsverzeichnis

Betrieb von Middleware und Frontend im Docker-Container

Der Betrieb von Volkszaehler im Docker-Container ist durchaus eine Alternative, sofern beispielsweise mehrere Anwendungen auf einem Server laufen oder der Anwender auf stark „vorgefertigte“ Komponenten zurückgreifen möchte.

Vorgefertigte Container

Im Docker-Hub gibt es vom Volkszaehler Projekt vorgefertigte Container. Dieser Beitrag bezieht sich ausschließlich auf den offiziellen Container https://hub.docker.com/r/volkszaehler/volkszaehler. Es gibt auch eine Vielzahl von inoffiziellen Container; teilweise mit anderer Bauart.

Ist der fertige Container direkt einsatzfähig?

Die Antwort lautet ganz klar Jein.

Ein Blick in das Docker-Compose File https://github.com/volkszaehler/volkszaehler.org/blob/master/docker-compose.yml zeigt uns, dass hier neben dem Volkszaehler noch eine Datenbank (MariaDB) und der Push-Server enthalten sind. Die Nutzung des fertigen Docker-Compose Files führt dazu, dass neben dem Volkszaehler auch eine neue Datenbankinstanz erzeugt wird. Wer „auf der grünen Wiese“ anfangen möchte, hat hiermit eine schnelle und unkomplizierte Lösung zur Hand. Wer allerdings bereits eine existierende Volkszaehler-Instanz mit einer separaten Datenbank hat oder ggf. MySQL verwenden möchte, stößt mit dem Lösungsansatz schnell an die Grenzen. Auch die Benutzerdaten und Datenbanknamen für die Datenbank sind in Volkszaehler fest vorgegeben. Credentials und DB-Namen müssen in der Datenbank zu den vordefinierten Werten in Volkszähler passen:

      MYSQL_DATABASE: volkszaehler
      MYSQL_USER: vz
      MYSQL_PASSWORD: demo
      MYSQL_ROOT_PASSWORD: admin_demo

Individuelle/angepasste Lösung

Wem diese Vorgaben nicht in der Konzept passen, muss leichte Veränderungen an dem vorgefertigten Image vornehmen.

Ich habe es bisher nicht geschafft das original GIT-Repo komplett durch einen Docker-Build Prozess laufen zu lassen (komplikationen mit PHP Versionen in den vorgefertigten Build-Umgebungen. Daher beziehe ich mich hierbei nur auf die Erweiterung der fertigen Container.

Zunächst erfolgt der Clone des gesamten Repositories in ein beliebiges Verzeichnis:

git clone git://github.com/volkszaehler/volkszaehler.org.git ~/volkszaehler.org

Aus diesem Clone benötigten wir folgende Dateien:

~/volkszaehler.org/etc/config.dist.yaml
~/volkszaehler.org/htdocs/js/options.js

In der config.dist.yaml muss der Datenbank Host und Passwort angepasst werden. Beispiel:

sed -i 's/  host: localhost/  host: mysqldb/g' config.dist.yaml
sed -i 's/  password: demo/  password: volkszaehler_password/g' config.dist.yaml

In der options.js muss der Eintrag

 url: 'api' 

zu

url: ''

angepasst werden.

In der options.js kann (optional!) der Demo-Server deaktiviert werden. Dazu müssen die folgenden Zeilen entfernt werden:

 }, {
  title: 'Volkszaehler Demo',
  url: 'https://demo.volkszaehler.org/middleware.php'
Achtet bitte auf die korrekte Klammer und Komma-Setzung. Der Block mit dem Title Local muss mit } abgeschlossen werden und darf danach kein Komma enthalten.

Die Dateien config.dist.yaml und ggf. options.js werden nach der Modifikation in einem neuen Order erstellt. In diesem Ordner erstellen wir ebenfalls jetzt das Dockerfile mit folgendem Inhalt:

FROM volkszaehler/volkszaehler
workdir .
COPY config.dist.yaml /vz/etc/config.yaml
COPY options.js /vz/htdocs/js/options.js

Im Nachgang kann der Dockerbuild Prozess gestartet werden. Ich habe dies ebenfalls über ein kleines Script gelöst:

#Adjust to local path for dockerfile, modified config.yaml, modified options.js
cd ~/docker/build/20210325_volkszaehler

#Definition of Datetime for Tag
dt=$(date +'%Y-%m-%d_%H-%M');

docker build . -t volkszaehler:$dt

Nach dem Build-Prozess kann der Container mit den persönlichen Anmeldedaten über ein docker-compose.yml File gestartet werden. Anbei ein Beispiel für ein minimalistisches Compose File.

version: '3'
services:


  volkszaehler:
    image: volkszaehler:2021-03-25_23-57
    ports:
    - 8080:8080
    restart: always
Die Datenbank und der Volkszaehler-Container müssen im gleichen Netzwerk liegen. Dies kann später auch in das Compose File integriert werden.
Ich habe den Volkszaehler Push-Server nicht im Einsatz. Daher habe ich hierzu keine Versuche unternommen. Der Push-Server kann/darf gerne noch ergänzt werden.

Aggregationen über die Middleware

Für die Aggregation über die benötigt man einen Job-Scheduler. Genau dieser Scheduler kann eine große Herausforderung sein. Es gibt verschiedene Lösungsansätze hierfür. In dieser Beschreibung wurde eine Lösung über Jobber verwendet.

Jobber

Das Dockerfile sieht wie folgt aus:

FROM jobber:latest
# Download latest listing of available packages:
User root

RUN apk add --no-cache mysql-client openssh

#Copy of SSH Keys
User jobberuser
RUN mkdir -p /home/jobberuser/.ssh
COPY id_rsa /home/jobberuser/.ssh/id_rsa
COPY id_rsa.pub /home/jobberuser/.ssh/id_rsa.pub

#Adjust SSH Config
User root
RUN chown -R jobberuser:jobberuser /home/jobberuser/.ssh
RUN echo "Host *" >> /etc/ssh/ssh_config
RUN echo "   StrictHostKeyChecking no" >> /etc/ssh/ssh_config

User jobberuser
In dem Verzeichnis des Dockerfiles müssen die SSH Keys hinterlegt vorhanden sein.
Die Anpassung der SSH_CONFIG kann, je nach Einsatzgebiet und weiterer Konfiguration ein Sicherheitsproblem sein/werden. Bitte Vorsicht bei extern erreichbaren Servern.

Die Berechtigungen für die Jobber-Verzeichnisse, auf dem Host, müssen wie folgt gesetzt sein:

sudo chown 1000:1000 <localpatchtojobber>/jobberuser
sudo chmod 0744 <localpatchtojobber>/jobberuser

Innerhalb des Docker Jobber Containers muss das .jobber File (im Home Verzeichnis vom jobberuser) wie folgt für die Aggregationen erweitert werden:

- name: VZ_AGG_DAY
  cmd: /home/jobberuser/vz_agg_day.sh
  time: '0 0 1 *'
  onError: Backoff
  
- name: VZ_AGG_HOUR
  cmd: /home/jobberuser/vz_agg_hour.sh
  time: '0 1 *'
  onError: Backoff
  
- name: VZ_AGG_MINUTE
  cmd: /home/jobberuser/vz_agg_minute.sh
  time: '0 */10'
  onError: Backoff

Das .jobber File ist die Konfiguration des Schedulers. Damit werden in diesem Fall Shell-Skripte aufgerufen.

Minimal-Inhalt der Shell-Skripte:

#/home/jobberuser/vz_agg_day.sh
ssh root@volkszaehler << EOF
php /vz/bin/aggregate run -m delta -l day >/dev/null
exit
EOF
#/home/jobberuser/vz_agg_hour.sh
ssh root@volkszaehler << EOF
php /vz/bin/aggregate run -m delta -l hour >/dev/null
exit
EOF
#/home/jobberuser/vz_agg_minute.sh
if [ -f /home/jobberuser/block-vz_aggregate.lock ]
	then
		echo "skipped" >> /home/jobberuser/vz_log_minute.txt
		exit 1
 else
 	touch /home/jobberuser/block-vz_aggregate.lock
 fi

ssh root@volkszaehler << EOF
php /vz/bin/aggregate run -m delta -l minute >/dev/null
exit
EOF

rm /home/jobberuser/block-vz_aggregate.lock
Die Lösung ist ohne Flock realisiert sondern mit „IF-ELSE“. Siehe hierzu auch: datenmengen

Volkszaehler Docker anpassen

Das minimalistische Volklszaehler Dockerfile muss für das Zusammenspiel mit Jobber erweitert werden:

FROM volkszaehler/volkszaehler

#SSH Server
RUN apk add --no-cache openssh

#RC-Service
RUN apk add --no-cache openrc
RUN rc-update add sshd

#Global Config for SSH and RC-Service
RUN ssh-keygen -A
RUN rc-status
RUN touch /run/openrc/softlevel

#Transfer SSH Key
RUN mkdir -p /root/.ssh
COPY id_rsa.pub /root/.ssh/authorized_keys

RUN echo "Host *" >> /etc/ssh/ssh_config
RUN echo "   StrictHostKeyChecking no" >> /etc/ssh/ssh_config

#define root password to get ssh access to work
RUN echo "root:root_pw" | chpasswd

#ENTRYPOINT ssh-keygen -A && rc-status && touch /run/openrc/softlevel &&/etc/init.d/sshd start && /vz/vendor/bin/ppm start -c /vz/etc/middleware.json --static-directory /vz/htdocs --cgi-path=/usr/local/bin/php
ENTRYPOINT /etc/init.d/sshd start && /vz/vendor/bin/ppm start -c /vz/etc/middleware.json --static-directory /vz/htdocs --cgi-path=/usr/local/bin/php


COPY config.dist.yaml /vz/etc/config.yaml
COPY options.js /vz/htdocs/js/options.js
In dem Verzeichnis des Dockerfiles muss der PUBLIC SSH KEY vorhanden sein.
Über
RUN echo "root:root_pw" | chpasswd

muss dem root User ein Passwort zugeteilt werden, ansonsten funktioniert der SSH-Zugriff nicht!

Docker Compose File

Ein fertiges Docker Compose File könnte wie folgt aussehen:

version: '3'

  mysqldb:
    image: mysql
    container_name: mysqldb
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    ports:
      - 3306:3306
      - 33060:33060
    volumes:
      - <replace_with_localpath>/mysql/etc/mysql/conf.d:/etc/mysql/conf.d
      - <replace_with_localpath>/mysql/var/lib/mysql:/var/lib/mysql

    volkszaehler:
    image: volkszaehler_ssh:2021-04-11_22-34
    container_name: volkszaehler
    ports:
      - 8080:8080
      - 8082:8082
      - 5582:5582
    depends_on:
      - mysqldb
    links:
      - mysqldb
    restart: always

  jobber_mysql_ssh:
    image: jobber_mysql_ssh:2021-04-11_15-59
    container_name: jobber
    restart: always
    volumes:
      - <replace_with_localpath>/jobber/jobberuser:/home/jobberuser

offene Punkte