Table of Contents
Allem voran: Docker allgemein ist ein sehr beliebtes und bekanntes Tool und bietet viele Möglichkeiten es zu verwenden und zu konfigurieren. Die folgende Beschreibung zeigt einen Weg der für mich eine funktionierende Entwicklungsumgebung in MacOS möglich gemacht hat.
Es ist nun schon einige Zeit bekannt, dass Docker unter MacOS Probleme macht. Meistens geht es um das Thema Performance wo, im Vergleich zu „native Linux“ und auch Windows MacOS sehr weit hinten liegt.
Das Problem
Die Basis des ganzen Problems liegt darin wie MacOS das Dateisystem von Docker Container mounted.
In Linux wird das sogenannte namespacing verwendet um die unterschiedlichen Prozesse und Ressourcen zu „gruppieren“ und damit nur in dieser Gruppe Zugriff aufeinander erhalten. Dieses namespacing Feature ist nur im Linux Kernel vorhanden und MacOS basiert nicht auf Linux.
Daher laufen Docker Container unter Linux quasi wie „native“ Applikationen da diese nicht wirklich „virtualisiert“ werden. Jedoch funktioniert dies eben unter MacOS nicht wie unter Linux, daher entsteht hier Latenz und Performance Probleme.
Folgendes Video (bzw. die Video Serie) von LiveOverflow kann ich definitiv empfehlen falls jemand mehr zum Thema namespacing und warum Linux docker containers keine VMs sind wissen möchte.
Die Lösung
Die folgende Beschreibung habe ich in diesem Blog-Post gefunden:
https://www.jeffgeerling.com/blog/2020/revisiting-docker-macs-performance-nfs-volumes
Daher danke an Jeff Geerling.
Zusammenfassend:
Bearbeite/Erstelle die Datei /etc/exports
und füge folgende Zeile hinzu:
/System/Volumes/Data -alldirs -mapall=501:20 localhost
Diese Datei ist eine Konfigurations-Datei für das NFS System welches unter MacOS zur Verfügung steht. Hier wird also der Pfad /System/Volumes/Data
inklusive aller Unterordner über den localhost zur Verfügung gestellt.
Hier kann es sein, dass ein Popup auftaucht, welches bzgl Berechtigungen Zugriff erfragt. Bitte dieses aktzeptieren.
Bearbeite/Erstelle die Datei /etc/nfs.conf
und füge folgende Zeile hinzu:
nfs.server.mount.require_resv_port = 0
Diese Zeile wird benötigt damit der NFS Daemon über einen beliebigen Port Verbindungen zulässt. Andernfalls kann der Docker keine Verbindung zum NFS Daemon herstellen.
Nun muss der NFS Daemon neu gestartet werden.
sudo nfsd restart
Final muss Full Disk Access
zum NFS Daemon gewährt werden.
Hierfür bitte unter System Preferences ==> Security & Privacy ==> Tab Privacy ==> Full Disk Access
Nun unten links auf das Schloss Symbol klicken um das bearbeiten der Einträge freizuschalten.
Danach das + Icon klicken um einen neuen Eintrag hinzuzufügen.
Nun bitte CMD + Shift + G drücken und den absoluten Pfad /sbin/nfsd eingeben und GO drücken
Der nfsd Daemon sollte nun in der Liste für Full Disk Access auftauchen und die Checkbox aktiviert sein.
Der letzte Schritt ist nun nur mehr die eigene docker-compose.yml anzupassen um NFS anstatt des „normalen volume binding“ zu verwenden.
Hier ein Beispiel für das „normalen volume binding“
version: "3.8"
services:
web:
container_name: sl_web
build:
context: .
dockerfile: docker/web/Dockerfile
ports:
# 'host:container'
- '80:80'
networks:
- frontend
- backend
volumes:
- ./webvol:/var/www/html:cached
mysql:
container_name: sl_db
image: mysql:5.7
command: mysqld
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--init-connect='SET NAMES UTF8;'
ports:
# 'host:container'
- '3306:3306'
networks:
- backend
environment:
- MYSQL_ROOT_PASSWORD=sl_db_root_password
- MYSQL_DATABASE=sl_db_name
- MYSQL_USER=sl_db_user
- MYSQL_PASSWORD=sl_db_password
phpmyadmin:
container_name: sl_pma
image: phpmyadmin/phpmyadmin
networks:
- frontend
- backend
environment:
PMA_HOST: mysql
PMA_PORT: 3306
PMA_USER: root
PMA_PASSWORD: root
ports:
# 'host:container'
- '8080:80'
networks:
frontend:
backend:
Wie im web
container zu sehen wird das „normalen volume binding“ verwendet um den Inhalt des webvol
Ordners des Hosts in den /var/www/html
Ordner des Containers zu mounten.
Um dies nun zu ändern bitte ./webvol:/var/www/html:cached
ändern auf nfsmount:/var/www/html:cached
web:
...
volumes:
- nfsmount:/var/www/html:cached
Hiermit wird Docker gesagt, dass das „named volume“ nfsmount
in den angegebenen containers Pfad gemounted werden soll.
Nun müssen wir aber das „named volume“ am Ende der docker-compose.yml noch definieren.
volumes:
nfsmount:
driver: local
driver_opts:
type: nfs
o: addr=host.docker.internal,rw,nolock,hard,nointr,nfsvers=3
device: ":$PWD/webvol"
Wie hier zu sehen muss nun der verwendete Document Root Pfad in der device
config definiert werden
Und damit sind wir fertig!
Zum testen füge eine nfo.php in den webvol Order, starte den Container und öffne localhost/nfo.php. Dieses sollte folgendes anzeigen
Das gesamte Projekt-Template kann HIER heruntergeladen werden.
Docker-Engine Debug-Mode standardmäßig aktiv
Nachdem ich mit einem Freund im BoltCMS Slack über das Docker Performance Problem geredet habe hat mich dieser darauf hingewiesen, dass Docker standardmäßig debugging aktiv hat in der Docker Engine (danke an Simon vom BoltCMS Slack Channel)
Wie hier zu sehen ist dieses hier auf true gesetzt.
Nachdem dieser Wert auf false gesetzt wurde hat sich die Performance meiner container wesentlich verbessert.
Ich habe keine Ahnung warum Docker diesen Wert standardmäßig setzt bzw. aktiviert (zu mindest am MacOS Client) aber diese Änderung in Kombination mit dem NFS mount hat mir einen wesentlichen Performance Schwung gebracht.