Matomo mit Docker
Ich habe die Software Matomo (früher Piwik) mit Docker auf meinem eigenen Server installiert.
Matomo (früher “Piwik”) ist eine Software zur Analyse von Zugriffen auf Websites, ähnlich wie Google Analytics. Im Unterschied dazu betreibt man Matomo auf dem eigenen Server, gibt also für die Analyse keine Daten an Dritte weiter. Auch wenn ich privat zahlreiche Google-Dienste nutze, wollte ich für diese Webseite lieber nicht Analytics einsetzen, um die Privatsphäre meiner Leser zu schützen.
Nun ist Matomo durchaus recht umfangreich, eine ordentliche Installation nicht mal eben so gemacht. Hier bietet sich Docker an, um möglichst wenige Komponenten auf der eigenen Maschine installieren (und pflegen!) zu müssen. Schematisch schaut das dann so aus:
Der nginx-Server oben nimmt Webanfragen entgegen, den habe ich sowieso installiert. Dort sind auch SSL-Zertifikate hinterlegt. Nginx wiederum gibt als reverse proxy die Anfragen weiter an 3 separate Prozesse, die als Docker Container laufen:
- Mysql Datenbank
- Matomo Anwendung
- nginx Frontend
Man fragt sich: Wozu der zusätzliche nginx-Prozess? Das Matomo-Docker-Image stellt keinen Webserver bereit, sondern ein FastCGI Interface. Es bedarf also eines zusätzlichen Webservers, der http-Anfragen an FastCGI übersetzt. Dazu kommen die statischen HTML-Bestandteile von Matomo, die im Docker-Image verborgen sind und einem externen Webserver nicht zugänglich sind.
Installation
Auf meinem Server ist Debian 9.6 (Stretch) installiert. Zusätzlich findest du hier eine Anleitung zur Installation von Docker und hier eine für die Installation von docker-compose. Um die Installation zu vollenden, sind diese Schritte auszuführen:
- User auf dem Server anlegen
- Docker-Dateien im $HOME dieses Users anlegen
- systemd-Eintrag erzeugen
- Frontend-Webserver konfigurieren
1. User anlegen
Ich lege einen Nutzer matomo
an, dem die Dateien später gehören sollen. Dieser Account darf sich nicht interaktiv anmelden und erhält daher kein Passwort. Der Nutzer ist Mitglied der Gruppe docker
, was dem Nutzer weitreichende Rechte einräumt. Achtung!
adduser --disabled-login matomo
adduser matomo docker
su - matomo
2. Docker-Dateien erzeugen
Wir brauchen drei Docker-Prozesse für Datenbank, Anwendung und Frontend. Um diese gebündelt zu definieren und zu starten, verwende ich docker-compose
. Das Composefile docker-compose.yml
schaut so aus:
db:
image: mariadb:latest
volumes:
- ./mysql/runtime2:/var/lib/mysql
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=1
app:
image: matomo:fpm
links:
- db
volumes:
- ./config:/var/www/html/config:rw
- ./logs:/var/www/html/logs
env_file:
- ./matomo.env
web:
image: nginx:latest
volumes:
- ./docker-nginx.conf:/etc/nginx/nginx.conf:ro
links:
- app
volumes_from:
- app
ports:
- 127.0.0.1:8001:80
Die Datei docker-nginx.conf
konfiguriert den inneren Nginx-Server. Der Pfad /var/www/html
bezeichnet den Pfad innerhalb des Docker-Containers der Anwendung, so schaut das dann aus:
user www-data;
events {
worker_connections 768;
}
http {
upstream backend {
server app:9000;
}
include /etc/nginx/mime.types;
default_type application/octet-stream;
gzip on;
gzip_disable "msie6";
server {
listen 80;
root /var/www/html/;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location ~ \.php$ {
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_intercept_errors on;
fastcgi_pass backend;
}
}
}
Zuletzt brauchen wir noch eine Datei namens matomo.env
mit der Umgebungsvariablen der Anwendung gesetzt werden können:
TZ=Europe/Berlin
REAL_IP_HEADER=X-Forwarded-For
LOG_LEVEL=DEBUG
Wenn alles fertig ist, solltest du jetzt diese Dateien angelegt haben:
/home/matomo# ls -l
total 24
-rw-r--r-- 1 matomo matomo 443 Jan 4 15:45 docker-compose.yml
-rw-r--r-- 1 matomo matomo 66 Jan 4 15:40 matomo.env
-rw-r--r-- 1 matomo matomo 1649 Jan 4 15:34 nginx.conf
Alles testen
Um deine Installation zu testen, kannst du sie als Nutzer matomo
starten und stoppen:
$ docker-compose up
...
# jetzt sollte der lokale Port 127.0.0.1:8081 verfügbar sein
$ docker-compose down
Welcher Port genau verwendet wird, ergibt sich aus der letzten Zeile der Datei docker-compose.yml
die den (Docker-internen) Port 80 des Frontend-nginx auf den nach aussen sichtbaren Port 8081 des Hosts umleitet. Beim ersten Start sollte dir Matomo die Konfigurationsseite präsentieren, in der man zB die Verbindung zur Datenbank angeben muss. Verwende dazu folgende Werte:
Name | Wert |
---|---|
Host | db |
DB | matomo |
user | root |
Passwort | (leer) |
Der Datenbankhost heisst db
, weil das in der Datei docker-compose.yml
oben so definiert ist. Die Container können untereinander diese Namen auflösen.
3. systemd Service definieren
Damit meine Matomo Instanz automatisch und im Hintergrund startet, verwende ich unter Debian 9.6 (stretch) systemd
. Meine Dienstdefinition in /etc/systemd/system/matomo.service
schaut so aus:
[Unit]
Description=Matomo service with docker compose
Requires=docker.service
After=docker.service nginx.service
[Service]
RestartSec=1
Restart=on-failure
User=matomo
WorkingDirectory=/home/matomo
ExecStart=/usr/local/bin/docker-compose -f /home/matomo/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f /home/matomo/docker-compose.yml stop
# use syslog for logging
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=matomo
[Install]
WantedBy=multi-user.target
Dieser Dienst muss jetzt noch durch folgende zwei Kommandos aktiviert und gestartet werden:
systemctl enable matomo
systemctl start matomo
Weitere Informationen zu systemd
findest du zB unter https://wiki.debian.org/systemd
4. Frontend Webserver mit nginx
Nachdem jetzt die drei Docker-Container definiert, verbunden und gestartet sind, ist der Port 8081 absichtlich so gestaltet, dass er von außen nicht zugänglich ist. Das erlauben wir über den Standard-Webserver, im Schaubild ganz oben die oberste Box.
Es gibt wahrscheinlich eine Millionen Wege, nginx oder Apache zu diesem Zweck zu konfigurieren. In meinem Setup verwende ich eine nginx-Datei pro virtuellem Server: Der Hostname lautet hier stats.software-berater.net
und die Datei dazu liegt in /etc/nginx/sites-available/stats.software-berater.net.conf
. So schaut sie aus:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name stats.example.com;
# managed by Certbot, redacted
ssl_certificate foo;
ssl_certificate_key bar;
location / {
proxy_pass http://127.0.0.1:8001;
}
}
Das SSL-Zertifikat erstelle ich mit LetsEncrypt, mit dem Kommando certbot --nginx
lasse ich mir neue Zertifikate erstellen und hinterlegen. Jetzt sollte deine brandneue Matomo-Instanz auf dem Hostnamen deiner Wahl SSL-geschützt im Netz sein. Herzlichen Glückwunsch!