Docker Desktop's Performance Odyssey Over a Year of Innovations
By Vladimir Mikhalev · Solutions Architect · Docker Captain · IBM Champion
Docker Desktop changed a lot over the past year. Most of it lands where you feel it day to day: startup time, file-sharing throughput, container-to-host networking. A slow Docker Desktop means more waiting and more context-switching while you work.
So I went through a year of releases and ran the benchmarks myself. Then I pulled out the changes that actually moved the numbers. Here’s what shifted, and by how much.
2023: Docker Desktop’s Performance Revolution
The 2023 releases are more than a version bump. Here’s what changed, area by area.
1. Docker Daemon Startup Time
Startup got noticeably faster this year. Some configurations now initialize in just over 5 seconds. You get into your containers without sitting around for the daemon.
| Mac amd64 | Mac arm64 | Win amd64 | Linux amd64 | |
|---|---|---|---|---|
| Time | 7.84 s | 5.24 s | 19.1 s | 9.50 s |
2. Container Operations with Hyperfine
I benchmarked Docker across versions with hyperfine. v4.22 beats v4.11 every time. Container operations got faster, plain and simple.
To install Hyperfine you can use the command:
brew install hyperfineUsing the hyperfine Tool
To benchmark Docker commands, we’ll use the hyperfine tool. Here’s how you can execute it:
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'What the flags do:
-
-ilets hyperfine run the benchmark in interactive mode, so you see results as they come in. -
-psets the warmup and benchmark commands for hyperfine. -
The warmup command,
docker stop ubuntu || :, tells Docker to stop the ubuntu container if it’s running. If it isn’t, it just moves on. -
The benchmark command,
docker run -it --rm ubuntu echo, starts the ubuntu container interactively and prints the current date and time.
Results for Docker Desktop v4.22
First Attempt:
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'Benchmark 1: docker run -it --rm ubuntu echoTime (mean ± σ): 44.3 ms ± 3.3 ms [User: 29.5 ms, System: 12.7 ms]Range (min … max): 39.7 ms … 49.6 ms 10 runsWarning: Ignoring non-zero exit code.Second Attempt:
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'Benchmark 1: docker run -it --rm ubuntu echoTime (mean ± σ): 46.3 ms ± 2.3 ms [User: 29.4 ms, System: 12.4 ms]Range (min … max): 43.1 ms … 52.5 ms 28 runsWarning: Ignoring non-zero exit code.Third Attempt:
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'Benchmark 1: docker run -it --rm ubuntu echoTime (mean ± σ): 46.5 ms ± 5.3 ms [User: 29.5 ms, System: 12.1 ms]Range (min … max): 39.0 ms … 63.5 ms 28 runsWarning: Ignoring non-zero exit code.The first attempt averaged 44.3 milliseconds, give or take 3.3 milliseconds. So most runs landed between 41.0 and 47.6 milliseconds. Fastest was 39.7, slowest 49.6.
Second attempt: 46.3 milliseconds on average, deviation 2.3 milliseconds. Most runs sat between 44.0 and 48.6 milliseconds. The quickest hit 43.1, the longest 52.5.
Third attempt was noisier. Average 46.5 milliseconds, but the deviation jumped to 5.3 milliseconds. That spreads the bulk of runs across 41.2 to 51.8 milliseconds. They ranged from 39.0 all the way up to 63.5.
Results for Docker Desktop v4.11
First Attempt:
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'Benchmark 1: docker run -it --rm ubuntu echoTime (mean ± σ): 59.7 ms ± 3.2 ms [User: 36.4 ms, System: 15.6 ms]Range (min … max): 55.0 ms … 68.3 ms 13 runsWarning: Ignoring non-zero exit code.Second Attempt:
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'Benchmark 1: docker run -it --rm ubuntu echoTime (mean ± σ): 56.7 ms ± 2.7 ms [User: 36.3 ms, System: 15.3 ms]Range (min … max): 51.7 ms … 62.5 ms 13 runsWarning: Ignoring non-zero exit code.Third Attempt:
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'Benchmark 1: docker run -it --rm ubuntu echoTime (mean ± σ): 59.8 ms ± 4.5 ms [User: 36.4 ms, System: 15.3 ms]Range (min … max): 51.2 ms … 69.5 ms 21 runsWarning: Ignoring non-zero exit code.Older version, slower numbers. First attempt averaged 59.7 milliseconds with a 3.2 millisecond deviation, so most runs fell between 56.5 and 62.9 milliseconds. Quickest was 55.0, longest 68.3.
Second attempt came in a bit better: 56.7 milliseconds on average, deviation 2.7 milliseconds. Most runs landed between 54.0 and 59.4 milliseconds. The spread ran from 51.7 to 62.5.
Third attempt averaged 59.8 milliseconds, deviation 4.5 milliseconds. Most runs were between 55.3 and 64.3 milliseconds. Fastest 51.2, slowest 69.5.
Final Results (Docker Desktop 4.11 vs 4.22)
| Docker Desktop v4.11 | Docker Desktop v4.22 | |
|---|---|---|
| First Attempt | 55.0 - 68.3 ms | 39.7 - 49.6 ms |
| Second Attempt | 51.7 - 62.5 ms | 43.1 - 52.5 ms |
| Third Attempt | 51.2 - 69.5 ms | 39.0 - 63.5 ms |
3. Resource Efficiency
The new Resource Saver is a real win. It watches what Docker is doing and trims usage down to what’s actually needed. Your Mac stays responsive even when the workload spikes.
Want to see it work? Start Docker Desktop and leave it idle for 30 seconds with no containers running. An icon shows up in the whale menu and in the dashboard sidebar. That’s Resource Saver kicking in.

Resource Saver tracks container activity. If Docker Desktop sits idle with nothing running for 30 seconds, it drops its memory and CPU usage on its own.
The chart below shows what Resource Saver does to the memory footprint of all Docker Desktop processes. I measured it with the footprint CLI command, which collects memory data for a process or a group of processes.

4.1 File Sharing with VirtioFS
File sharing has always been the sore spot in containerized development. VirtioFS changes that. File I/O is much faster now. Builds finish sooner, data moves quicker, and the whole loop feels less sluggish.
Types of File Sharing Mechanism
| File Sharing Mechanism | Description | Additional Notes |
|---|---|---|
| VirtioFS | A native file sharing mechanism supported by Docker Desktop. It’s the fastest as it doesn’t need extra software. | Default file-sharing mechanism in DD 4.22. |
| gRPC FUSE | Uses the gRPC protocol for file sharing. While slower than VirtioFS, it’s faster than other mechanisms. | Default option in DD 2.4.0.0 (2020). Consumes less CPU than osxfs, especially with numerous file events on the host. |
| qemu-grpcfuse | Uses the qemu hypervisor for file sharing. It’s the slowest mechanism but viable for building Redis images. | |
| hyperkit-grpcfuse | Employs the hyperkit hypervisor for file sharing. Its speed is comparable to qemu-grpcfuse. | |
| osxfs | A file system driver bridging macOS file system and the Linux-based system used by Docker containers. | Default file-sharing mechanism in Docker for Mac 1.12.x. |
Enable VirtioFS
Open Docker Desktop settings and go to the “General” tab. Find “Choose file sharing implementation for your containers” and pick “VirtioFS”. Then click “Apply & Restart”.

Steps to Set Up and Test VirtioFS
Create a directory using the command:
mkdir dataPopulate the Directory with a Large Data File (1GB of random data) using the command:
dd if=/dev/zero of=data/data.img bs=1M count=1000Next, let’s build the Docker Image using the command:
First, create a Dockerfile with the following content:
FROM ubuntu:latest
VOLUME /data
CMD ["bash"]Then, build the Docker image using the command:
docker build -t virtiofs-demo:latest .Run the Docker Container using the command:
docker run -it --rm -v "$(pwd)/data:/data" virtiofs-demoList the Running Containers using the command:
docker psExpected output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESe47eb4731c80 virtiofs-demo "bash" 5 minutes ago Up 5 minutes gifted_lichtermanNext, measure File Copy Time into the Container
time docker cp gifted_lichterman:/data/data.img data/data.imgExpected result:
Successfully copied 1.05GB to /Users/ajeetsraina/july/virt/data/data.imgdocker cp gifted_lichterman:/data/data.img data/data.img 0.61s user 1.84s system 36% cpu 6.750 totalPerformance Comparison
Comparing Docker Desktop 4.22 vs 4.11 (without VirtioFS enabled)
| Data Size: 10GB Data Transfer | Docker Desktop v4.11 | Docker Desktop v4.22 |
|---|---|---|
| Run #1 | 7 min 13.21 s | 5 min 11.10 s |
| Run #2 | 6 min 47.89 s | 5 min 04.08 s |
| Run #3 | 7 min 04.75 s | 5 min 02.08 s |
Comparing Docker Desktop 4.22 vs 4.11 (with VirtioFS enabled)
| Data Size: 10GB Data Transfer | Docker Desktop v4.11 | Docker Desktop v4.22 |
|---|---|---|
| Run #1 | 2 min 18.55 s | 1 min 04.44 s |
| Run #2 | 2 min 20.23 s | 1 min 06.21 s |
| Run #3 | 2 min 15.65 s | 1 min 05.39 s |
4.2 Evaluating Docker Desktop’s File-Sharing Performance
Every upgrade is partly about performance. With Docker Desktop, moving between versions isn’t only new features. It’s also tightening what’s already there. The switch from VPNKit to gVisor mattered here. Container-to-host networking on macOS got up to 5x faster, so the things that used to crawl, like package downloads, move quickly now.
In this part I measure how long it takes to build a Redis image from source using Docker Desktop’s file sharing. The source comes in over a bind mount. I time the build inside the container.
Redis Build Process
# !/bin/bash
rm -rf /tmp/redisdocker run --rm -v /tmp:/tmp alpine sh -c \ 'cd /tmp ; apk add git ; git clone https://github.com/redis/redis --depth 1'
docker run --rm -v /tmp/redis:/tmp/redis ubuntu bash -c \ 'cd /tmp/redis ; apt update && apt install -y make gcc ; make distclean && time make'Redis Build Performance
| Parameter | VirtioFS | gRPC FUSE | qemu-grpcfuse | hyperkit-grpcfuse |
|---|---|---|---|---|
| Redis Build | 2.78 min | 3.54 min | 6.68 min | 5.19 min |

Postgres Build Process
First, the setup. The script below creates a Postgres network, starts a server, and fires off a pgbench client.
# !/bin/bash
IMG=postgres:alpineNET=postgresnetTESTDIR=/tmp/postgrestest/dataPGNAME=postgrestestPGPASS=postgrespass
docker network rm -q $NET &>/dev/null
echo "Setting up postgres network..."docker network create $NET
rm -rf $TESTDIRmkdir -p $TESTDIR
echo "Initiating postgres server..."docker run --name=${PGNAME} -e POSTGRES_PASSWORD=postgrespass --network ${NET} -p 5432:5432 -v ${TESTDIR}:/var/lib/postgresql/data -d ${IMG}
echo "Launching postgres pgbench client..."docker run --network ${NET} alpine sh -c \ 'apk add postgresql ; export PGPASSWORD=postgrespass; \ pgbench --host=postgrestest -U postgres -i -s 10 postgres ; \ pgbench --host=postgrestest -U postgres -c 10 -t 10 postgres'
docker stop ${PGNAME} &>/dev/nulldocker rm ${PGNAME} &>/dev/nulldocker network rm -q $NET &>/dev/nullPostgres Build Performance
| Scenario | 4.11.1 | 4.22 |
|---|---|---|
| Postgresql tps (transactions/s) | 1000 tps | 2600 tps |
Version 4.22 leaves 4.11.1 behind on transactions per second. It hits 2600 tps, more than double the 1000 tps the older build managed.
The file-sharing mechanism you pick really moves build times. For something like a Redis build, VirtioFS is the one to use.
Postgres transactions also improved a lot in 4.22, which points to real work under the hood in this release.
VirtioFS wins on Redis builds, but pick your mechanism around the project. Compatibility and your specific needs come first.
That jump in Postgres throughput from 4.11.1 to 4.22 is the kind of thing that makes the upgrade pay for itself.
5. Container Networking Enhancements
The 2023 updates leaned hard on networking, especially on macOS. Containers talk to each other more smoothly now. Data moves faster, latency drops, and the whole setup runs tighter.
The big change was swapping VPNKit for gVisor on container-to-host networking. That landed in Docker Desktop 4.19, released in March 2023.
NOTEIn Docker Desktop 4.19, container-to-host networking performance was boosted by 5x on macOS, achieved by replacing vpnkit with the TCP/IP stack from the gVisor project.
gVisor is a lightweight, sandboxed container runtime that runs in user space. It’s built on the Linux kernel but implemented in user space, which gives it an edge over VPNKit, a kernel-based solution.
If your containers reach out to external servers, say npm install or apt-get pulling packages, this speedup pays off immediately.
Enabling gVisor
To check that Docker Desktop is on gVisor by default, run:
cat ~/Library/Group\ Containers/group.com.docker/settings.json | grep -i networkIf you want VPNKit back, add “networkType”:“vpnkit” to your settings.json file.
Why gVisor over VPNKit:
- Performance: gVisor is faster than VPNKit, so containers run quicker.
- Security: It’s sandboxed, which means better protection against vulnerabilities.
- Resource Efficiency: It uses fewer resources than VPNKit, so your Mac has more to spare.
Networking Benchmarks
Container to Container
Benchmarking Tool: iperf3/netperf
# !/bin/bash
IMG=dockerpinata/iperf3:2.1NET=iperf3netSERVER=iperf3serverCLIENT=iperf3client
docker rm -f $SERVER &>/dev/nulldocker network rm -q $NET &>/dev/null
echo "Creating iperf3 network..."docker network create $NET
echo "Starting iperf3 server..."docker run --rm -d --name=${SERVER} --network=${NET} ${IMG} /usr/bin/iperf3 -s -1
echo "Starting iperf3 client..."docker run --rm --name=${CLIENT} --network=${NET} ${IMG} /usr/bin/iperf3 -c ${SERVER}
docker rm -f $SERVER &>/dev/nulldocker network rm -q $NET &>/dev/null| Platform | Speed |
|---|---|
| Mac amd64 | 41.5 Gb/s |
| Mac arm64 | 81.7 Gb/s |
| Win amd64 | 46.1 Gb/s |
| Linux amd64 | 56.3 Gb/s |
Container to Host
Benchmarking Tool: iperf3/netperf
# !/bin/bash
IMG=dockerpinata/iperf3:2.1
# This can be used to remove previous hanging iperf3 servers
# pkill iperf3
echo "Starting iperf3 server..."iperf3 -s -1 &IPERF3_SERVER_PID=$!
echo "Starting iperf3 client..."docker run --rm ${IMG} /usr/bin/iperf3 -c host.docker.internal
kill $IPERF3_SERVER_PID &>/dev/null| Platform | Speed |
|---|---|
| Mac amd64 | 686 Mb/s |
| Mac arm64 | 1.50 Gb/s |
| Win amd64 | 596 Mb/s |
| Linux amd64 | 1.62 Gb/s |
Host to Container
Benchmarking Tool: iperf3/netperf
# !/bin/bash
IMG=dockerpinata/iperf3:2.1SERVER=iperf3serverdocker rm -f $SERVER &>/dev/nullecho "Starting iperf3 server..."docker run --rm -d -p 5201:5201 --name=${SERVER} ${IMG} /usr/bin/iperf3 -s -1echo "Starting iperf3 client..."iperf3 -c localhostdocker rm -f $SERVER &>/dev/null| Scenario | 4.11.1 | 4.22 |
|---|---|---|
| Container to Container | 60 Gb/s | 72 Gb/s |
| Host to Container | 420 Mb/s | 1.4 Gb/s |
| Container to Host/internet | 930 Mb/s | 18 Gb/s |
6. Hardware Compatibility: Embracing Apple Silicon and Rosetta
Docker added a Rosetta feature, and it’s a smart move. It closes the gap between Intel and Apple Silicon, so you get the same experience whatever hardware you’re on.

That means you can drop this command:
docker run --platform=linux/amd64Like with VirtioFS, Rosetta brought speedups too. Someone in our community clocked a 7x boost, most of it on a DB migration that used to crawl.
What this means in practice
Every release this year chipped at the same problem: the gap between running a container on your laptop and running it the way production does. On macOS, the gVisor networking switch alone justifies the upgrade. It brought up to 5x faster container-to-host networking.
Still on an older version? The gap isn’t cosmetic anymore. You can read it in the build and startup numbers above. Update, push your own workload through it, and compare against what you had before.
Happy coding, and until next time, keep containerizing!
The Verdict
Inconvenient truths about shipping in the AI era
Container security, platform engineering, and the agentic shift — tested in production, argued without the hype. The verdict reaches your inbox the moment there's one worth sending.
Related Posts
- 1Your Knowledge Is a Depreciating Asset. Judgment Compounds.Opinion & Culture · AI made reproducible knowledge free, so technical expertise is now a depreciating asset. Judgment is the one that compounds. Here is how to move your weight.
- 2The Senior Engineer Signal: The 2026 Risk Your Velocity Metrics HideOpinion & Culture · Juniors get the biggest boost from AI; seniors trust it least. That split is your earliest read on engineering risk, and on the talent you're about to lose.
- 3Agent Sprawl: The 2026 Engineering Risk Your Auditor Hasn't Named YetOpinion & Culture · Unknown numbers of AI coding agents run in parallel — no audit trail, no isolation, no per-team measurement. By 2026 that's an audit finding.
- 4I Tested an AI Agent on My Live Systems. Here Is the Blast Radius Assessment Every Engineer Is Skipping.Opinion & Culture · Everyone is buying Mac Minis and installing AI agents. I tested one in isolation. Here is the architectural framework for deployment that the Instagram hype does not include.
Random Posts
- 1Configure AWS CLIDevOps & Cloud · Learn how to configure AWS CLI with IAM credentials. Step-by-step guide for setting up secure access, managing keys, and running AWS commands via terminal.
- 2Configure Exchange Server 2010SysAdmin & IT Pro · Complete guide to configuring Exchange Server 2010. Learn mailbox setup, certificates, DNS, email policies, and secure mail delivery—step by step.
- 3I Tested an AI Agent on My Live Systems. Here Is the Blast Radius Assessment Every Engineer Is Skipping.Opinion & Culture · Everyone is buying Mac Minis and installing AI agents. I tested one in isolation. Here is the architectural framework for deployment that the Instagram hype does not include.
- 4DevOps and Platform Engineering DynamicsDevOps & Cloud · Explore the comprehensive impact of DevOps and Platform Engineering on software development, detailing key strategies, technological innovations, and future trends shaping the industry.