Docker for Mac Edge now supports a :cached flag that can be appended to volumes which helps find a significant boost to read performance, see https://github.com/docker/for-mac/issues/77.
What is your recommendation on how to apply this tag to volume mappings? Would you apply it to all of them?
Output of fin config:
fin config output
COMPOSE_PROJECT_NAME_SAFE: docksalblt
COMPOSE_FILE:
/Users/les.peabody/.docksal/stacks/volumes-bind.yml
/Users/les.peabody/.docksal/stacks/stack-acquia.yml
/Users/les.peabody/Sites/docksalblt/.docksal/docksal.yml
ENV_FILE:
/Users/les.peabody/Sites/docksalblt/.docksal/docksal.env
PROJECT_ROOT: /Users/les.peabody/Sites/docksalblt
DOCROOT: docroot
VIRTUAL_HOST: docksalblt.docksal
VIRTUAL_HOST_ALIASES: *.docksalblt.docksal
IP: 192.168.64.100
MYSQL: 192.168.64.100:32778
Docker Compose configuration
---------------------
networks: {}
services:
cli:
dns:
- 192.168.64.100
- ''
environment:
HOST_GID: '1106437719'
HOST_UID: '1729411499'
XDEBUG_ENABLED: '0'
hostname: cli
image: lpeabody/blt-cli
volumes:
- host_home:/.home:ro
- docksal_ssh_agent:/.ssh-agent:ro
- project_root:/var/www:rw
db:
dns:
- 192.168.64.100
- ''
environment:
MYSQL_DATABASE: default
MYSQL_PASSWORD: user
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: user
hostname: db
image: docksal/db:1.0-mysql-5.5
ports:
- 3306/tcp
volumes:
- project_root:/var/www:ro
memcached:
dns:
- 192.168.64.100
- ''
environment:
MEMCACHED_MEMORY_LIMIT: '128'
hostname: memcached
image: memcached
solr:
dns:
- 192.168.64.100
- ''
hostname: solr
image: docksal/solr:1.0-solr4
varnish:
depends_on:
web:
condition: service_started
dns:
- 192.168.64.100
- ''
environment:
VARNISH_BACKEND_HOST: web
hostname: varnish
image: docksal/varnish:1.0-varnish4
labels:
io.docksal.virtual-host: varnish.docksalblt.docksal
web:
depends_on:
cli:
condition: service_started
dns:
- 192.168.64.100
- ''
environment:
APACHE_DOCUMENTROOT: /var/www/docroot
hostname: web
image: docksal/web:1.0-apache2.2
labels:
io.docksal.project-root: /Users/les.peabody/Sites/docksalblt
io.docksal.virtual-host: docksalblt.docksal,*.docksalblt.docksal
volumes:
- project_root:/var/www:ro
version: '2.1'
volumes:
docksal_ssh_agent:
external: true
host_home:
driver: local
driver_opts:
device: /Users/les.peabody
o: bind
type: none
project_root:
driver: local
driver_opts:
device: /Users/les.peabody/Sites/docksalblt
o: bind
type: none
---------------------
For now I would think it's fin config generate and edit resulting docksal.yml as much as you need.
I guess we might include this option in future as default one, when it's stable.
@achekulaev they are looking at a stable mid-June release, actually, in 17.06. I'll try your recommendation and note performance improvements, if any, here.
@lpeabody you want to add :cached on the project_root volume in cli, like this:
cli:
...
volumes:
# Project root volume
- project_root:/var/www:rw,cached
I installed the latest edge release of Docker for Mac (Version 17.06.0-rc1-ce-mac13 (18169)) to test this. Either I'm doing something wrong, or there is no difference.
I'm running my standard test with time drush si -y (3 runs) and seeing no changes in the results regardless of the flag value.
Without :cached
real 0m58.845s
real 0m58.577s
real 1m5.246s
With :cached
real 1m6.226s
real 1m7.792s
real 1m1.457s
@lmakarov Confirmed, I see the same results, running at 2m38s and 2m45s for my si command (running a custom installation profile). Definitely something to keep plugging at though. If others are seeing vastly improved results like @geerlingguy does here (https://github.com/docker/for-mac/issues/1592#issuecomment-303607515) then maybe we're doing something that is a bit of?
One thing he notes is that he wants to be using rw,delegated but sounds like he's replacing rw,delegated with cached on it's own? But then cli wouldn't be able to write to the volume, I think?
I've been doing more testing and figured out what was going on. I'm going to publish a blog post at some point, but for now, here are some key points.
osxfs:cached does not work with named volumes, so project_root:/var/www:rw,cached won't work. I reported the issue in https://github.com/docker/for-mac/issues/1899
As a workaround, the following can be used:
cli:
...
volumes:
# Project root volume
- ${PROJECT_ROOT}:/var/www-cached:rw,cached
Here we create another mount point without a named volume. To confirm that cached kicked in:
/Applications/Docker.app/Contents/MacOS/com.docker.osxfs state | grep $(basename $(pwd))
Do a sudo cp -a /var/www /var/www-native and now you have 3 options to test against: osxfs, osxfs:cached, native fs.
docker@cli:/var/www/docroot$ for i in {1..3}; do (time drush si -y); done
docker@cli:/var/www-cached/docroot$ for i in {1..3}; do (time drush si -y); done
docker@cli:/var/www-native/docroot$ for i in {1..3}; do (time drush si -y); done
I've also tested with the forth option: NFS with Docker for Mac. Results below.

cached is definitely an improvement over raw osxfs and it even outperforms the nfs mount (though, it's not clear why nfs has such a terrible (2x!) cold start time).
Looking at those results you could think "Yay! Let's all switch to Docker for Mac and use cached".
Well, let's take a look back at what VirtualBox with NFS has to offer (using the same test):

VirtualBox + NFS still outperforms Docker for Mac + osxfs:cached by 35%. On top of that, osxfsadds a considerable CPU overhead on the host when in use.
When comparing native file system performance between D4M (with xhyve under the hood ) and VirtualBox, D4M is as fast (or even slightly faster) as VirtualBox.
Once we add file sharing to the mix, the situation changes drastically.
It's not clear to me, why NFS results are so much different, when native fs results are pretty much the same between Docker for Mac and VirtualBox.
I know is an old thread, but..
@lmakarov have you ever compared the container fs vs the native fs (running all natively on macOS - apache, mysql/fs, php fpm.
For me that's always been what pushes me away of dockerized alternatives (and the fact that I am pretty used to setting my own box the way I want to). Even with docker fairly new raw mode and the cached flag, just clearing cache on drupal could be 2/3+ x slower on a bare drupal install.
@hanoii
have you ever compared the container fs vs the native fs (running all natively on macOS - apache, mysql/fs, php fpm.
I'm testing with a bunch of VMs (Linux, Mac and several Windows variations) running in VMware on my Mac. For day to day use I'm either on Docker for Mac or VirtualBox. Linux in VMware is as close to the native fs/etc. performance on Mac as possible (or may even outperform Mac).
The reason I'm not comparing with a native stack on Mac is due to the setup overhead. I could probably install MAMP, but for an apples to apples comparison that will still require adjustments to the settings to match them with what Docksal ships with.
For me that's always been what pushes me away of dockerized alternatives
Take a look at the Unison volumes option in Docksal:
It provides the best possible fs performance you get get out of a Docker/virtualized setup.
It does have some tradeoffs as well (like extra space usage and initial sync delay), but if performance is your biggest concerns, then it is your best bet.
I'd be very interested to see how your native stack performance on Mac compares to the Unison option in Docksal, so please share your results if you decide to try it!
@lmakarov
A couple years ago, when docker was not yet that mainstream I set up a project-wise local environment with vagrant, debian and unison. It didn't go well, the management issues and different situations for each developer eventually made it not worth the time. But it's amazing that unison is still the solution for native performance on virtual boxes (whether virtual box or docker) at least on mac. I am unsure on the situation on Windows
I'll give it a try at some point, and attempt to compare then and give you a shout on my findings.
I really like where this, lando and other docker approaches are going and I think docker is THE tool to eventually make something consistent for local devs. I might not ever be for me. I work on a lot of projects weekly and I like having everything one bookmark away, without having to init/start/stop anything.
I am just hoping that native fs will get to docker at some point.
Linux in VMware is as close to the native fs/etc. performance on Mac as possible (or may even outperform Mac).
This is an interesting claim, and what do you use? Docksal inside a linux instance on vmware with unison between your host and vmware?
Thanks for the feedback.
@hanoii
and what do you use?
For the "eat your own dog food" reasons I'm sticking with the most mainstream option at the moment, which is Docker for Mac (with osxfs:cached).
When performance is a concern, I switch to VirtualBox (with NFS) - the battle tested option that has been around for quite some time. Docker for Mac + Unison is still quite experimental.
Running a Linux VM with Docksal inside is less convenient. I'm using it for testing Docksal on Linux purposes only. For daily use, I'd recommend it to Windows users, as they suffer the most from the shared/network fs performance issues.
@lmakarov out of curiosity and to give docksal an init try I started the drupal8 example with unison volumes
Running time fin drush cr gave me an average of ~3.2s on a few calls, counting only the last to compare the same rough benchmark
While
running time drush cr on a bare install on a native stack
gives me ~1.3s
And this is just on an empty bare drupal8, I assume as more modules/themes get loaded the wider the spread would be.
and the same time fin drush cr on the non-unison volumes gives me around ~5.2s
This is all using latest docker edge
@hanoii Thanks for sharing the your test results. There's clearly a big gap there.
One of the tough issues with virtualized environments (meaning VirtualBox and xhyve (Docker for Mac) in this context) is the overhead of the CPU virtualization - it's expensive. For workloads that cannot be efficiently broken into multiple threads (or just don't support that) enabling more that a single core for a VM will actually slow things down (reference).
For very large databases, though, enabling multiple cores may result in better performance (as mentioned in the blog post I reference previously).
Native stacks will always have an advantage here. Though, a 250% difference like in your case is quite too much :)
What do you use for the native stack? I'm curious whether you have some specific settings/optimizations applied for PHP, MySQL, etc.
@lmakarov I haven't done much optimizations to be honest.
It's all the latest homebrew packages: mariadb, httpd24, php7.1 (I have all 5.6, 7.0 and 7.2 installed as well at the same time, through fpm). I did turn off xdebug on my native stack and I noticed that was affecting performance but as far as I can tell, xdebug was also off on all docksal instance I tested. I didn't enable it at least and saw it was disabled on docksal.env
I've tried lando again as well, they don't provide unison, but a brand new d8 (a bit slow to install) then took ~4.7 to clear cache. Not a huge different but a tiny better. They are using the delegated osxfs-caching instead of cached. just throwing out more info.
But still unison is a huge benefit.
@hanoii thanks a lot for taking your time to test this!
Could I ask you for a favor to do another test for me? You see, fin drush is slow in part because spawning an interactive session into a running container is a slow process (slow meaning 1-2 seconds overhead to spawn it).
Could you start your drupal8 example, and first open open interactive session into cli
fin bash
and only the then run time drush cr from there. This way you will test the real time of running drush inside the container, rather than time of running drush + interactive session spawn overhead.
For me the results are the following.
NFS mapped volumes ~3.5s
docker@cli:/var/www/docroot$ time drush cr
Cache rebuild complete. [ok]
real 0m3.563s
user 0m0.810s
sys 0m0.400s
docker@cli:/var/www/docroot$ time drush cr
Cache rebuild complete. [ok]
real 0m3.376s
user 0m0.810s
sys 0m0.380s
docker@cli:/var/www/docroot$ time drush cr
Cache rebuild complete. [ok]
real 0m3.444s
user 0m0.810s
sys 0m0.410s
Unison volumes 1.5-2s
docker@cli:/var/www/docroot$ time drush cr
Cache rebuild complete. [ok]
real 0m2.000s
user 0m0.730s
sys 0m0.430s
docker@cli:/var/www/docroot$ time drush cr
Cache rebuild complete. [ok]
real 0m1.510s
user 0m0.740s
sys 0m0.180s
docker@cli:/var/www/docroot$ time drush cr
Cache rebuild complete. [ok]
real 0m1.453s
user 0m0.750s
sys 0m0.120s
Update.
I have installed MAMP to test. All default. PHP 7.1, same drupal8 site (copied over sources).
Result is 1.5s which seems on par with Unison volumes, more consistent but not much difference in average.
11:20:36 /Applications/MAMP/htdocs/sites/default
搂 time ../../vendor/drush/drush/drush cr
[success] Cache rebuild complete.
real 0m1.587s
user 0m0.833s
sys 0m0.176s
11:20:44 /Applications/MAMP/htdocs/sites/default
搂 time ../../vendor/drush/drush/drush cr
[success] Cache rebuild complete.
real 0m1.526s
user 0m0.851s
sys 0m0.177s
11:20:48 /Applications/MAMP/htdocs/sites/default
搂 time ../../vendor/drush/drush/drush cr
[success] Cache rebuild complete.
real 0m1.513s
user 0m0.852s
sys 0m0.172s
@achekulaev sure
I don't have nfs setup, (as I went with the native docker mac approach), but osxfs-cached:cached gives me ~3.5s within the container
and with unison ~1.35 in average vs ~1.25 in native.
That's good! I also tested it through the web interface (clearing cache) and timing just the post request and it's pretty close too. Some times it even beat the native stack.
This is promising. The next test is has to be the real thing, actually trying on an active project and do some benchmarking there, hopefully with solr,mail and maybe redis, something more "real"
I also wonder how unison would cope with composer installs/npm installs that touches a lot of files. On the lando thread where I brought thsi up, they said unison brought a lot of issues to them.
Have you ever used unison it on a full scale project? 20+modules, solr, etc.? What's your experience with it.
@hanoii I have used Unison to launch large scale projects (400+ modules), but mostly to verify things or do minor changes, haven't really heavily used it for development.
Some people in some situations reported issues when switching git branches, as it touches a lot of files. And you have to bear in mind, that switching git branches will need time to propagate through Unison (fin logs unison will help with the sync status).
right. and also the fact that's duplicating everything could also be an issue if available space is somehow a constrain
One of the things I have in plans is the ultimate performance option. No sync + Cloud9 for editing.
DOCKSAL_VOLUMES=copy option would tell fin to perform one time copy of the project folder. No follow-up syncs, just one time copy. But one would need to edit those files somehow after that. This is an issue, unless one is hardcore Vim fan, in which case it wouldn't be an issue at all.
Use (currently experimental) Cloud9 IDE, which looks very appealing at this point to edit files inside container, perform commits, tests etc.
This would be the most performant option, on par with native but with all the Docksal benefits.
@lmakarov @achekulaev can I also bother you with a slightly off topic question, but related..
What's your thoughts on the current performance with the VirtualBox option. Is it faster than docker for the time being? And vs native host filesystem. Any complains with performance on virtualbox?
Thanks!
@hanoii , @achekulaev did a great blog post about that very topic: https://blog.docksal.io/docker-for-mac-virtualbox-and-docker-performance-f0a606229f6c
@hanoii when mapped via NFS (the default mode) then VirtualBox is on average 20% faster than Docker for Mac, and native file system is on average 20% faster than VirtualBox.
When Unison volumes are used, then there is almost no difference between VirtualBox, Docker for Mac and Native file system.
@achekulaev We have had some issues with using the Unison volumes on our Macs for development. The largest two are:
vendor folder that was synced back during a previous setup)In contrast, NFS works pretty much transparently, uses less disk space and is fast. Although Docker for Mac seems to be becoming mainstream, we would be arguably worse off...
@GMTA I am not sure I understand you about the last phrase about being worse off. As compared to what? Which approach to chose for your project is purely your choice. There is no silver bullet. There are pros and cons with each approach.
@achekulaev I agree and it is subjective, but for most workloads I've seen better performance and less issues with NFS than with the Unison approach. The only real downside is lack of inotify which is largely compensated for by the improved performance.
I just now discovered that Docker for Mac can be coerced into supporting NFS together with Docksal by following instructions from this thread:
https://github.com/IFSight/d4m-nfs/issues/55
Basically:
DOCKSAL_VOLUMES to nfsoverrides-osxfs.yml (e.g. by renaming) so the cli volume is mapped correctlyMaybe this helps someone looking for the same gains without losing sync functionality :-)
@GMTA ah! It was not obvious that you were advocating in favor of using NFS with Docker for Mac. It is a good point that some might be fine with it. I'm pretty sure we could add an exception, that if DOCKSAL_VOLUMES is defined by user to be NFS then fin would not override it with osxfs.
Do I understand you right?
@achekulaev That is completely right! There is an exception when running with DOCKSAL_NATIVE=0 which causes the override to be skipped, which is not the case when running with Docker for Mac.
In fact, the only reason to use the osxfs overrides is when you're _not_ using DOCKSAL_VOLUMES=nfs and you're running on a Mac I guess?
In this case it would be Docker with NFS? I'd be curious about that option. In theory it should have the same performance as VirtualBox and NFS, right?
@hanoii Docker for Mac + NFS was slower than VirtualBox + NFS in the tests done almost a year ago. See https://github.com/docksal/docksal/issues/249#issuecomment-320376680 for details. I should probably do another round of comparison with the recent Docker/Docker for Mac versions.
I would love to see some different benchmarking here. Maybe we need a standard "suite" of tests. I see some people testing "drush si" and some using "drush cr". For NFS the big bottle neck is when you manage lots of smaller files. So I use tests like "rm -rf node_modules && npm install" or "rm -rf vendor && composer install". These kind of tests will show large performance drops for NFS, which is why I prefer either unison or osxfs.
One thing I noticed with unison is that when doing something like "rm -rf vendor" within the cli container, files on my local file system are not deleted. This is a clever workaround for a bug in unison that often causes it to crash when you quickly delete and recreate a massive number of files, but is a problem for ensuring the container and local are truly in sync.
@mike-potter I've been performing benchmarks on our own PHP projects with simple rm -rf vendor && time composer install invocations. On docker-machine with NFS I saw improvements of 30-40% w/ respect to osxfs:cached and on Docker for Mac I saw improvements between 20-30%. A possible explanation for this difference could be that the docker-machine has one single big NFS mount whereas the Docker for Mac approach entails configuring NFS volumes for your projects.
Anyway, not sure how recent your experience is with NFS and Docker but I would recommend revisiting your benchmarks!
This issue's discussion is a bit too good/too useful to have it here on a closed issue. Is it too bad of an idea to highjack it, re-open/rename it and maybe link it somewhere on the project page?
@hanoii I was literally thinking just about an hour ago that maybe this gets re-opened? I've been following the discussion along and enjoying the insight.
@GMTA Here are my benchmarks from docker-machine with VirtualBox on Mac with rm -rf vendor && time composer install (Mac OS 10.12.4)
docker-machine + Pure Container: 25s
docker-machine + NFS: 9m40s
docker-machine + Unison: 29s
This was for a real D8 client project (based on Acquia Lightning). The dominant time for NFS was doing drupal/core although all packages were noticeably slower.
When using Docker4Mac the composer timing was:
Docker for Mac + osxfs (cached): 3m39s
Docker for Mac + without overrides-osxfs.yml: 4m59s
Docker for Mac + NFS: 3m4s
(Edited: Got NFS working with D4M) Didn't use Unison on D4M because it doesn't sync file deletions in the container which doesn't make it viable for us.
So this looks like D4M overcomes the NFS issues that docker-machine has with small files. But not seeing any big performance boost of NFS vs osxfs.
(Edited: Hmm, not sure this was really using NFS, so still learning how to use that. docker inspect still showed using bind, so the last two D4M runs were essentially the same)
(Edited: OK, got NFS working. In my "permission denied" error message it gave an IP address, so in my /etc/exports I replaced "localhost" with this IP and restarted everything. Then verified project-root was using NFS) Updated above NFS benchmark. I might not be seeing full NFS performance since I'm on older Mac OSX 10.12.4.
@mike-potter I wonder why docker machine + NFS has that big of hit in comparison to the other options and that much above D4M + NFS. Shouldn't it be more or less the same underneath?
And while you are there, do you happen to be able to try that natively (on the actual host)? I'd assume it should be pretty close to the pure container benchmark.
It's been over a year since I looked into it, but I remember there was an issue with PHP not caching the "stat" of files via NFS, so anything using is_dir() was slow (which resulted in patches to drush to not scan node_modules or bower_components). But I don't remember why it was so bad with VirtualBox. This was back when I couldn't get osxfs to work at all with docker-machine, so I know they have different drivers (or at least did). Been away from this for a year so things might have changed.
Unfortunately I can't run composer locally...I try to keep all my tools installed in containers and right now local composer is complaining about my PHP version.
@mike-potter there is a new fresh option on the table. https://docs.docker.com/docker-for-mac/mutagen-caching/
Just tried it. Native fs performance. Very fast. Takes time to sync though but should be much more stable than unison and there is a UI in form of Docker Desktop.
I didn't share the whole Projects folder though, but rather created a separate "cached" folder inside and applied mutagen to that folder only.
We've actually been using Mutagen here for several months. I has been a huge improvement and was very easy to set up. We just set DOCKSAL_VOLUMES=none and then create a mutagen.yml file for the project. It never crashes like Unison did and has great performance. We share the whole project but use the ignore config for stuff like vendor, node_modules etc that only need to be available inside the docker containers and not locally. Then we wrote a fin sync command that will do a one-time "sync all" if a Dev ever wants to have vendor/node_modules locally for IDE debugging etc.
I did see that Docker Desktop was adding Mutagen support but haven't played with that specifically yet. We just did a brew install mutagen and went from there. Nice to see we picked the right solution and it might just be built into Docker Desktop. I don't agree with just having a separate "cached" folder but we'll see how it evolves. I noticed a session on Mutagen in Docker Desktop in the upcoming DockerCon virtual conference.,
@mike-potter , good advice. I read about Mutagen in another issue post #1259 written by you, and now I'm trying it because I don't like the Unison solution already present in Docksal for speeding up performance while using Docker Desktop in MacOS because:
Usually I perform tests on an already installed heavy Drupal 8 website executing drush cr or installing / uninstalling modules using the Drupal interface and as of my first not empirical tests (I didn't measure time) I can say the Mutagen solution is impressive as well as using Unison container which I gave a try before switching to Mutagen because unlike with Unison the first sync and next cli container recreation require less than a couple of minutes (maybe just one).
Usually I don't suffer performances using normal NFS volumes until I enable xdebug in cli container. When xdebug is enabled on normal NFS volumes the performances are a mess.
Another important point to consider when testing Mutagen solution mostly to improve the performances with xdebug enabled, Docker Desktop must be always restarted if Mac OS awake form sleep otherwise even with Mutagen enabled performances will again become a mess.
I will keep testing it.
xdebug should only affect the current docksal CLI container and shouldn't need a full Docker Desktop restart. I have a script to toggle xdebug that runs via fin within the CLI container (using #: exec_target = cli) which edits the php.ini to toggle the xdebug extension on/off and then does a sudo supervisorctl restart php-fpm to just restart the php-fpm process. We use this to turn off xdebug when doing something like a composer command (composer is REALLY slow with xdebug enabled).
After testing and appreciating the usefulness of Mutagen in combination with Docksal I'm starting to use a custom Docksal command I created to initialize, start, stop and restart a Docksal project with a Mutagen project inside at the same time. If interested in you can find it in Mutagen for Docksal repository.
We also add troubles with NFS being too slow for a big Drupal project.
Unison has great performances but the initial sync takes forever because we have a lot of files.
We tried Mutagen and it works really well so far, so having it integrated in Docksal would be really great!
Most helpful comment
@achekulaev We have had some issues with using the Unison volumes on our Macs for development. The largest two are:
vendorfolder that was synced back during a previous setup)In contrast, NFS works pretty much transparently, uses less disk space and is fast. Although Docker for Mac seems to be becoming mainstream, we would be arguably worse off...