Skip to content

Instantly share code, notes, and snippets.

@danmichaelo
Last active October 26, 2020 08:58
Show Gist options
  • Select an option

  • Save danmichaelo/272b3af375376f6f8198955779f5922d to your computer and use it in GitHub Desktop.

Select an option

Save danmichaelo/272b3af375376f6f8198955779f5922d to your computer and use it in GitHub Desktop.
Docker performance with shared volumes on mac

Docker for Mac used to use osxfuse for file sharing, which has both been slow and caused excessive CPU usage. The :cached and :delegated option made things a little bit better, but it was still quite bad if you were syncing large directories. In May 2020, the Docker team added "Improve Mac File system performance" to their roadmap and started experimenting with replacing osxfs with mutagen. Which actually worked great, but it required synchronization running in the background, which adds complexity, and in the end it was not considered stable enough, or something like that, and dropped in favour of gRPC FUSE – which is said to solve the CPU usage problem, but which generally seems to be slower than the already slow osxfuse 😱

Mutagen (Docker Desktop Community Edge 2.3.4.0)

Mutagen was added to the Edge channel in May (2.3.1.0), and further improved upon until 2.3.4.0.

Testing with 2.3.4.0, it gives near-native performance: (even though the timing doesn't include the time the background sync takes to catch up)

$ docker run -it -v /private/tmp/www2:/var/www:delegated alpine time dd if=/dev/zero of=/var/www/test.dat bs=1024 count=100000
100000+0 records in
100000+0 records out
real	0m 0.47s
user	0m 0.08s
sys	0m 0.35s

gRPC FUSE (Docker Desktop Community Stable 2.4.0.0)

The new default in 2.4.0.0 is really quite slow:

$ docker run -it -v /private/tmp/www2:/var/www:delegated alpine time dd if=/dev/zero of=/var/www/test.dat bs=1024 count=100000
100000+0 records in
100000+0 records out
real	1m 12.33s
user	0m 0.67s
sys	0m 4.86s

osxfuse (Docker Desktop Community Stable 2.4.0.0)

Disabling gRPC FUSE disabled in 2.4.0.0 takes us back to osxfuse:

$ docker run -it -v /private/tmp/www2:/var/www:delegated alpine time dd if=/dev/zero of=/var/www/test.dat bs=1024 count=100000
100000+0 records in
100000+0 records out
real	0m 28.36s
user	0m 0.45s
sys	0m 2.96s

NFS (Docker Desktop Community Stable 2.4.0.0)

The Docker team didn't consider NFS an option because it doesn't support filesystem events (inotify). But if you don't need that, it could still be a good option. Having added

/System/Volumes/Data/private/tmp -alldirs localhost

to etc/exports, we can run

$ mkdir /private/tmp/www-nfs
$ docker volume create --driver local --opt "type=nfs" --opt "device=:/System/Volumes/Data/private/tmp/www-nfs" --opt "o=addr=host.docker.internal,rw,nolock,hard,nointr,nfsvers=3" nfstmp
$ time docker run -it -u $(id -u) -v nfstmp:/var/www alpine time dd if=/dev/zero of=/var/www/test.dat bs=1024 count=100000
100000+0 records in
100000+0 records out
real	0m4.840s
user	0m0.170s
sys	0m0.210s

Summing up

NFS seems like a good middle ground between performance and stability/complexity.

Alternatively, Mutagen can be used standalone, but it requires some setup for each project. Mutagen Compose looks promising, in that it abstracts away much of the added complexity, and comes with built-in support for user mapping. It's still in active development, so could be interesting to monitor and perhaps get back to in a few months time to see if it has caught on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment