macOS Docker use NFS Volume to get a better performance

macOS Docker NFS Volume

Why volumes on macOS work so slow? Docker For Mac runs the docker server within the virtual machine. The host machine shares the file system with the VM using osxfs. According to the documentation:


There are a number of issues with the performance of directories bind-mounted with osxfs. In particular, writes of small blocks, and traversals of large directories are currently slow. Additionally, containers that perform large numbers of directory operations, such as repeated scans of large directory trees, may suffer from poor performance.


My blog project based on Hexo(with next theme) consist of lots of files. Docker needs to keep in sync tons of files between the host machine and the container.

NFS Volume

The docker-compose allows defining the NFS volume that can be mounted to the container. The only thing you need to do is to configure and expose your NFS server.

If you want to mount volumes from NFS, you need to expose selected directories in /etc/export file.

First edit the /etc/exports file. If it doesn’t exist, which was my case, create it and eidt:

1
2
3
4
5
6
7
# /etc/exports

# For MacOS Catalina Users
/System/Volumes/Data -alldirs -mapall=501:20 localhost

# For Others MacOS Versions
/Users -alldirs -mapall=501:20 localhost

Edit /etc/nfs.conf to tell the NFS daemon to allow connections from any port. This is necessary as Docker NFS connections can be blocked.

1
2
3
# /etc/nfs.conf

nfs.server.mount.require_resv_port = 0

Restart NFS to take .

1
$ sudo nfsd restart

Check NFS service status.

1
2
3
$ sudo nfsd status
nfsd service is enabled
nfsd is running (pid 7612, 8 threads)

Test

Now we are going to configure your docker-compose.yml so that the volumes are made via NFS. Below is a simple example that can be easily adapted to the project you are working on:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '3'

services:
# docker-compose run app sh
# docker-compose run --service-ports app sh
app:
build:
context: ../
dockerfile: docker/Dockerfile
ports:
- "4008:4000"
# restart: on-failure
volumes:
- nfsmount:/app

volumes:
nfsmount:
driver: local
driver_opts:
type: nfs
o: addr=host.docker.internal,rw,nolock,hard,nointr,nfsvers=3
device: ":/System/Volumes/Data/${PWD}"

You see we have a volume called nfsmount, which can be called anything you want, which has some extra parameters for your volume.

That done, you can now upload your containers and see the huge difference this one will bring to you.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ docker-compose run app bash
docker-compose run app bashCreating network "blog-hexo-docker-compose_default" with the default driver
Creating volume "blog-hexo-docker-compose_nfsmount" with local driver
Creating blog-hexo-docker-compose_app_run ... done
bash-5.0# hexo g
INFO Validating config
INFO ==================================
███╗ ██╗███████╗██╗ ██╗████████╗
████╗ ██║██╔════╝╚██╗██╔╝╚══██╔══╝
██╔██╗ ██║█████╗ ╚███╔╝ ██║
██║╚██╗██║██╔══╝ ██╔██╗ ██║
██║ ╚████║███████╗██╔╝ ██╗ ██║
╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═╝
========================================
NexT version 8.0.0-rc.5
Documentation: https://theme-next.js.org
========================================
INFO Start processing
INFO Files loaded in 1.67 s
INFO Deleted: tags/Cert-Manager/index.html
INFO Deleted: 2020/07/04/git/Git-Large-File-Storage-LFS-version-large-files-on-the-remote-git-server/index.html
INFO Generated: tags/cert-manager/index.html
INFO Generated: 2020/07/04/Git/Git-Large-File-Storage-LFS-version-large-files-on-the-remote-git-server/index.html
INFO 2 files generated in 1.88 s

References

[1] Slow docker on Mac? Use NFS! | Yii Academy - https://www.yiiacademy.com.br/en/2020/04/30/slow-docker-on-mac-use-nfs/

[2] Speed up docker using NFS volumes – FINGO Blog - https://blog.fingo.pl/speed-up-docker-using-nfs-volumes/