First of all: Docker in general is very popular topic and has many ways how it can be used, configured and worked with. The following statements are how I interpreted the whole docker ecosystem and how I personally got a working docker environment with MacOS.
It has been known for a long time, that Docker has performance issues under MacOS. You can also find many other tutorials online which seem to improve the performance but in my experience most of them didn’t.
Basically Docker for MacOS doesn’t “mount” the filesystem of the container the same way as Linux does.
In Linux Docker basically “separates” all its containers via namespacing. This namespacing feature is present in the Linux kernel but MacOS is not based on Linux.
Therefore in Linux there is no difference between files on the host and container system but MacOS has to circumvent this feature “somehow”. And this “somehow” basically creates a whole lot of latency which reduces the performance dramatically.
I can definitely recommend this whole series from LiveOverflow where he goes deeper into the whole namespacing topic and why linux docker containers are not VMs (if you are interested)
I found the following blog article which basically has the solution + performance benchmarks in them:
So definitely kudos to him!
Edit/Add the file
/etc/exports and add the following line:
/System/Volumes/Data -alldirs -mapall=501:20 localhost
This file is a config file used by the NFS system available under MacOS. So therefore this line exports the directory
/System/Volumes/Data including all subdirectories to the localhost.
It could be that a permission popup shows while saving this file. Please accept that.
Edit/add the file
/etc/nfs.conf and add the following line:
nfs.server.mount.require_resv_port = 0
This line is required to tell the NFS daemon to allow connections from any port. Otherwise Docker’s NFS connections may be blocked.
Now restart the NFS Daemon to reload the new config
sudo nfsd restart
Finally I had to add
Full Disk Access to the NFS Daemon.
Go to System Preferences ==> Security & Privacy ==> Tab Privacy ==> Full Disk Access
Click the lock at the bottom left to allow editing the entries.
Then click on the + icon to add a new entry.
Now press CMD + Shift + G to enter the absolute path /sbin/nfsd and klick GO
The nfsd should now appear in the list of apps which should have Full Disk Access and the checkbox next to it should be checked.
The last step is to adjust your docker-compose.yml to actually use NFS instead of the normal volume binding.
Here is an example of an “old” docker-compose.yml
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:
As you can see the
web container uses a normal volume binding to mount the hosts
webvol folder to the containers
And here are the main changes which need to be done for the NFS implementation
Adjust the volume mount from
web: ... volumes: - nfsmount:/var/www/html:cached
This tells docker to use the “named volume”
nfsmount to mount into the containers path.
Now we have to define the “named volume” at the bottom of our docker-compose.yml
volumes: nfsmount: driver: local driver_opts: type: nfs o: addr=host.docker.internal,rw,nolock,hard,nointr,nfsvers=3 device: ":$PWD/webvol"
As you can see the adjusted document root path is now being set in the
device config of the volume definition.
And with that we should be fine.
Adding a nfo.php to the webvol folder, starting the docker instance and browsing localhost/nfo.php should result it.
You can download this whole project template HERE.
Docker-Engine Debug-Mode default on
After talking about docker performance issues with a friend of mine (thanks Simon from BoltCMS Slack) he told me, that Docker itself has a debug mode which drastically reduces performance.
And as you can see here this setting is set to true.
After setting that to false and recreating my containers my performance had drastically increased.
I have no idea why this is a default setting Docker sets (for at leat the MacOS Client) but this in combination with the NFS mount was the solution to my performance problems I had Docker on MacOS.