Docker Desktop 2.2, WSL 2, Drupal 8, and Symfony Performance
I’ve been writing about two stack update tracks going on recently. In today’s article I want to cover some of the questions I have related to the performance improvement that each stack update brings, and how they relate to each other.
Sometimes I confuse which performance upgrade belongs to which stack, because you need to only utter the word performance and as an operations engineer I have the same euphoric reaction:
- Updating Docker Desktop to version 2.2.
- Updating Windows Subsystem for Linux from version 1 to version 2.
I had read a article of how Docker performance improved recently while using Symfony. Since Drupal does in fact use Symfony, this is two-hundred percent relevant to me (I ran statsd on my brain to measure relevance). And then I forgot to save the article somewhere useful. I went to Microsoft’s documentation but couldn’t find the article!
After spending what seemed like an hour looking at Chrome browser’s history logs (not helped by the fact that it merges my Google Pixel’s history too), it happens that the Symfony-related performance improvement was related to Docker Desktop and not WSL. Here’s the article:
- New Filesharing Implementation in Docker Desktop Windows Improves Developer Inner Loop UX, by David Scott (Docker), December 12, 2019.
There’s two main things in that article that justified an hour searching for it:
The latest Edge release of Docker Desktop for Windows 2.1.7.0 has a completely new filesharing implementation using Filesystem in Userspace (FUSE) instead of Samba.
And, perhaps more relevant to my interests:
uses caching to (for example) reduce page load time in Symfony by up to 60%;
Symfony! Ahem, cough Drupal, cough. Performance!
.
I mention Drupal surreptitiously because Symfony does not depend on Drupal, but Drupal 8 depends on Symfony more than a millennial junkie on his daddy’s trust fund.
There’s two main questions that arise the article penned by Docker own’s David Scott:
.
#1 What is the caching implementation? Is it internally tucked away from the user (automatic, no user control)? Or is it tied to Docker volume consistency: consistent
, cached
, or delegated
(user has control).
.
#2 Are Docker 2.2.x file system improvements tied to also upgrading to WSL 2?
.
.
.
TL;DR: as a Docker Desktop user:
.
Do I benefit when I store the files in Windows Subsystem for Linux and mount them to Docker?
YES.
Up to 60% as proven by a simulated Symfony workload. Mileage may vary depending on your particular workload, and whether it makes use of caching, where caching is your application’s internal caching, and not to be confused with Docker’s volume caching, which is separate and clarified further below.
Do I benefit when I store the files in Windows/Mac and share them to Docker?
NO.
Not for massive performance improvements anyways. But you would get newer features anyways courtesy of the Docker engine, and both Docker Desktop 2.2 and WSL 2 run probably faster by themselves, so hey! Why not upgrade anyways? Just don’t expect any life-altering performance improvements.
Do I need to tweak any bind volumes from their default consistency from consistent
to cached
or delegated
?
NO.
You will reap benefits from thew new Docker Desktop version 2.2 using the default consistent
volume consistency. But if you want to put your Docker workloads on crack try some consistency optimizations by switching some of the mounts to cached
or delegated
. More on that later.
Do I need to upgrade from WSL 1 to WSL 2?
YES.
When I upgraded from my previous version to Docker Desktop version 2.2, I still have WSL version 1 installed on my Windows machine. Docker Desktop would not allow me to enable the WSL integration. Once I upgraded WSL to version 2 (and restarted the machine, obviously), Docker Desktop 2.2 allowed me to enable the WSL integration. And so the cycle of life was complete.
.
.
Okay, now for the actual questions (and memes).
Question #1: What is the caching implementation ?
.
.
When Scott ran his benchmark, what consistency did he use? David’s Scott’s earlier article kindly links to the workload he ran to test the new WSL 2 setup:
On Scott’s Symfony demo Makefile, the command to run the Docker workload is:
Here’s a breakdown of Scott’s demo. With regards to Scott’s demo volume mount instruction, which is found on the Github project I linked to:
-v $(shell pwd)/www:/var/www djs55/symfony-demo
You can see that the volume --volume
, -v
instruction does not specify mount consistency. To do that, you would probably need to employ the --mount
flag, which seems to offer a richer set of options.
As referenced by the --mount
flag documentation, the service create command reference mentions full options for bind mounts, including mount consistency: default
, consistent
(also the default), cached
, and delegated
.
But Scott’s demo is not using --mount
, much less specifying mount consistency.
In addition, over at Configure mount consistency for macOS (Docker Docs):
By default, … shares are fully-consistent, meaning that every time a write happens on the macOS host or through a mount in a container, the changes are flushed to disk so that all participants in the share have a fully-consistent view.
.
With all these data points we can make the following inferences:
- Docker’s
default
volume mount consistency isconsistent
across Mac and Windows Docker Desktop implementations. - Scott’s demo does not specify consistency, therefore the Symfony demo’s volume consistency is the
default
, which would meanconsistent
. - Therefore, Scott must have achieved up to a 60% performance improvement on Symfony workloads using the default volume
consistent
consistency!
In addition:
- The user ultimately has control of the caching strategy and can further optimize it to be
cached
ordelegated
in accordance to his current Docker workloads — or leave it at thedefault
should he/she need increased data integrity. - Out of the box, users will see a performance improvement using the
default
caching strategy ofconsistent
, as denoted by the various data points quoted above (Docker Docs, Scott’s Symfony Demo).
.
.
Question #2: Are Docker 2.2.x file system improvements tied to WSL 2 (Or, do I really need to upgrade them BOTH)?
This is a bit harder to glean from Scott’s Symfony demo.
- I can’t glean from the Symfony demo if the
docker run
command was from outside WSL, on a Windows host, or inside WSL from say, Ubuntu WSL. - The Docker Desktop release linked by Scott, release 2.1.7.0 does tout prominently brand new WSL integration, specifically WSL version 2.
On Simon Ferquel’s Introducing the Docker Desktop WSL 2 Backend (October 24, 2019), under the “Linux Workspaces support” section, it reads:
Using this we are actually able to expose the (Docker Desktop) daemon to the user distro (Ubuntu, Alpine, etc.), and we can access the user distro files (Ubuntu, etc.) from within our contained environment (Docker Desktop) with native Linux performance. Emphasis is mine.
I want re-emphasize that the following line:
… with native Linux performance.
What this section is saying is basically that because the Docker daemon (aka Docker Desktop) is running inside the WSL space, the Docker daemon has an easier time accessing files made available by other distributions running inside the same WSL space.
.
Don’t believe me? Here’s a direct screenshot from Simon Ferquel’s article on Docker.com (how many times am I going to link to it):
.
This was my reaction after reading that line:
.
If you read Scott’s article, you’ll come to understand the mind blowing fact that they’re running the Docker deamon itself as a separate, isolated WSL distribution, instead of inside Hyper V. Let me pause here. What this means is that:
- When you
docker run
from Ubuntu WSL — you ain’t talking to Windows Hyper V.docker run
is talking to another WSL distribution, which contains the Docker daemon itself… This WSL distro to WSL distro communication is what allows near-native performance improvements, which makes sense… - When you talk to Docker Desktop from Windows, say you open
cmd.exe
, and typedocker run
, you ain’t talking to Windows Hyper V either… - If you execute
docker run
fromcmd.exe
, that command is going into WSL, and talking to the Docker daemon provided by Docker Desktop, running inside WSL.
Inception ensues:
In addition to those mind levelers:
- Simon’s article is from October 24th, 2019;
- Scott’s article follows shortly afterwards — December 12th, 2019;
- Docker Desktop 2.2 only got announced on January 21st, 2020;
- Both Simon and Scott are Docker employees, therefore probably using shared best practices;
And, David Scott’s Symfony Demo article:
- Links to Docker Desktop 2.1.7.0 (or greater), which introduced brand-new WSL support, and;
- Native Linux performance from WSL (user) distro to WSL (docker) distro is touted in Simon’s article, under Linux Workspaces Support; and achieved as of 2.1.7.0.
With those data points correlated, I’d say that David Scott:
- Installed the Docker client using
apt-get
inside an Ubuntu WSL distribution; - Ran the Symfony demo using the Docker client installed inside Ubuntu WSL distribution, in order to achieve that near Linux performance that you get when mounting volumes from one WSL distribution (Ubuntu) to another WSL distribution (Docker).
Therefore it is with a high degree of confidence that I conclude: Docker 2.2 file system improvements are indeed tied to WSL 2 integration.
Case in point, before upgrading to Docker Desktop 2.2 and WSL version 2, I used to have the following in my Ubuntu WSL distrubtion’s .profile
:
That variable DOCKER_HOST
, allowed my Ubuntu WSL docker
client to communicate with the Docker daemon provided by Docker Desktop, which in turn ran in Hyper V, and exposed tcp://localhost:2375
to Docker clients.
Without this line my Ubuntu WSL would not be able to talk to Docker Desktop.
After upgrading both Docker Desktop and WSL (and yes, I had to upgrade both), I had to comment that line out in order for the docker
client inside WSL to talk to Docker Desktop-provided Docker daemon.
Using docker info
you can confirm which Docker daemon your Docker client is talking to, and in my case, confirm that both Windows cmd.exe
(or PowerShell), and Ubuntu in WSL 2 are talking to the same exact Docker daemon:
Notice the matching Docker ID on both PowerShell and Ubuntu WSL shells:
NSBJ:CBIG:7F5B:NTFL:RRRF:FR7Z:R7CP:E5RX:VQ3V:Y4VV:4THO:NGF6
In order to attain these performance gains, you will need to observe the following details:
- Locate your source code inside WSL.
- Install the
docker
anddocker-compose
clients inside WSL. - Run
docker
anddocker-compose
commands from inside WSL. - Do: Mount your source code from your WSL distribution into Docker Desktop.
- Do Not: Mount source code on the host Windows machine into Docker Desktop.
While it is still possible to mount Windows files into Docker Desktop 2.2, you wont achieve that lucrative up to 60% performance gain (slaps heartily on lid of laptop).
.
.
.
Tuning Docker Volume Consistency
.
.
Today I mentioned at the beginning of my article volume consistency tuning.
While I hopefully established quickly that it is not the #1 deciding factor in achieving performance gains when upgrading Docker Desktop and WSL, it could still make a unnoticeable or outsize impact depending on your individual Docker workloads.
The following articles offer in-depth advice on bind volume mount consistency (The Good), and in-particular details about volume consistency when applied to the Drupal and PHP stacks (The Excellent). The only downside is that Docker on Mac Performance was written in mid-2017 (The Bad), and while Speeding up Docker on MacOS was written on July 2019, both of these articles are written for Docker for Mac (The Ugly).
The silver lining on both of these detailed articles, especially the older one (Spoiler: it has benchmarks), is that the advice on volume mount consistency and performance, the last missing piece of the puzzle for today’s article should still generally hold. I hope. There’s only one way to find out: doing benchmarks. Specifically real-life workloads on Windows WSL 2, Composer, and Drupal. But I’m out of time for this article, so let there be links (below).
.
And links shall be had, oh my:
- Managing Application Data: bind mounts, Docker Docs.
- Configure mount consistency for macOS, Docker Docs.
- Performance tuning for volume mounts (shared filesystems), Amazee.io, 2017. Contains Drupal and Composer benchmarks!
- Speeding up Docker on MacOS, 2019. Covers PHP stack and cache consistencies.
.
Bibliography and Snippets
.
Some more links and information I used to compile this story.
.
From the Docker Desktop 2.2 release notes: https://docs.docker.com/docker-for-windows/release-notes/#docker-desktop-community-2200
The experimental Docker Desktop WSL 2 backend architecture introduces support for Kubernetes, provides an updated Docker daemon, offers VPN-friendly networking, and additional features. For more information, see Docker Desktop WSL 2 backend.
From https://docs.docker.com/docker-for-windows/wsl-tech-preview/:
WSL 2 introduces a significant architectural change as it is a full Linux kernel built by Microsoft, allowing Linux containers to run natively without emulation. With Docker Desktop running on WSL 2, users can leverage Linux workspaces and avoid having to maintain both Linux and Windows build scripts.
Docker Desktop also leverages the dynamic memory allocation feature in WSL 2 to greatly improve the resource consumption. This means, Docker Desktop only uses the required amount of CPU and memory resources it needs, while enabling CPU and memory-intensive tasks such as building a container to run much faster.
Additionally, with WSL 2, the time required to start a Docker daemon after a cold start is significantly faster. It takes less than 2 seconds to start the Docker daemon when compared to tens of seconds in the current version of Docker Desktop.
From https://docs.docker.com/docker-for-windows/edge-release-notes/#docker-desktop-community-2170:
File sharing: The new gRPC FUSE system is no longer experimental and is enabled by default even when experimental features are turned off.
Docker Desktop release 2.2 announcement, by Ben De St. Paer-Gotch (Docker), January 21, 2019.
This new architecture for WSL 2 allows users to … turn off the traditional Hyper V VM while working with WSL 2…
Traditionally with Docker Desktop on Windows, we have relied upon the Samba protocol to manage the interaction between the Linux file system working with Docker and the Windows file system. We have now replaced this with gRPC FUSE, which: uses caching to (for example) reduce page load time in Symfony by up to 60%; supports Linux inotify events, triggering automatic recompilation / reload when the source code is changed;
Introducing the Docker Desktop WSL 2 Backend by Docker’s own Simon Ferquel, October 24, 2019.
5 Things to Try with Docker Desktop WSL 2 Tech Preview, also by Simon himself, July 31, 2019.
In addition, Simon’s last blog post links to two Microsoft Development Blog items, written by Microsoft’s Craig Loewen. If you’ve been following Docker Desktop and WSL on Windows you’ve probably seen them, but I’ll still be useful to link them as they provide useful high-level information as well:
WSL 2 is now available in Windows Insiders, Craig Loewen (Microsoft), June 12, 2019.
Announcing WSL 2, Craig Loewen (Microsoft), May 6, 2019.
.
And since I mentioned that Drupal was related to Symfony, in case you’re curious:
- https://ffwagency.com/learning/blog/why-symfony-drupal-8-and-how-does-change-things
- https://drupalize.me/blog/201802/symfony-4-and-drupal
- https://blog.sensiolabs.com/2018/04/23/symfony-drupal-8-benefits-training/
.
.
.