logrotate mit NGINX in Docker-Containern

Da NGINX auf verschiedene Art und Weise seine Logfiles schreiben kann, verwendet man unter normalen Installationen das USR1-Signal. Die Verwendung wird im NGINX-Wiki erklärt. Dies zwingt NGINX dazu alle offenen Logfiles erneut zu öffnen, z. B. wenn das Logfile durch logrotate oder andere Zwecke verschoben, gelöscht oder umbenannt wurde. Bei Docker-Containern haben wir mehrere Ansätze.

Der einfachste ist es dem Container direkt das Signal an die Container ID zu schicken. Um eine Übersicht der laufenden Container zu erhalten, reicht ein Aufruf von docker ps. Die Angabe der ID muss nicht vollständig sein, eine ID von 836fbe33ff87 kann z. B. abgekürzt werden zu 836 in weiteren Befehlen, solange diese Kombination eindeutig ist und nicht angeprangert wird.

Nun können wir direkt signalisieren:

docker kill -s USR1 836

Dies funktioniert auch in einem Docker-Compose-Netzwerk, wobei wir hier die NGINX-Logfiles am besten über ein Volume nach außen legen.

services:
  frontend:
    image: nginx
    volumes:
      - ./logs:/var/log/nginx

Dadurch können wir vom Hostsystem sowohl auf die Logfiles zugreifen als auch das Signal senden.

docker-compose kill -s USR1 frontend

Dies können wir nun mit einer logrotate-Konfiguration , z. B. in /etc/logrotate.d/website, verbinden.

/home/docker/website/logs/*.log {
  weekly
  missingok
  rotate 56
  compress
  delaycompress
  notifempty
  sharedscripts
  postrotate
    cd /home/docker/website \
      && /usr/local/bin/docker-compose kill -s USR1 frontend
  endscript
}

Nun können wir eine Rotation erzwingen um diese neuen Einstellungen zu testen.

To try the configuration just force the rotate command.

logrotate --force /etc/logrotate.d/website

Es gibt noch eine weitere Alternative, diese sollte aber nur in der Not angewandt werden.

Die Option heißt copytruncate und ist dafür gedacht alle bestehenden Logeinträge in ein rotiertes Logfile zu kopieren und das bestehende nicht zu löschen, sondern zu leeren.

Bei gleichzeitigem Schreibvorgang durch NGINX und der Logfile-Rotation könnte das Delta verloren gehen, wenn die copytruncate verwendet wird.

Dies ist hilfreich bei Programmen, die ein Logfile dauerhaft offen halten und nur schwer zur Freigabe des selbigen genötigt werden können.

/home/docker/website/logs/*.log {
  weekly
  missingok
  rotate 56
  compress
  delaycompress
  notifempty
  sharedscripts
  copytruncate
}
Damit verzichtet man auf die `postrotate` Einstellung, aber ob ein möglicher Verlust die Vereinfachung wert ist, muss man selbst entscheiden.