2765 words
14 minutes

Docker Desktop's Performance Odyssey Over a Year of Innovations

Hello, fellow developers and tech enthusiasts! Today, I’m thrilled to walk you through the remarkable transformation Docker Desktop has undergone over the past year. Docker Desktop’s performance is not just a matter of numbers; it directly impacts our productivity, workflow efficiency, and overall development experience. A faster and more efficient Docker Desktop means less waiting, fewer interruptions, and a smoother development process.

As someone who’s always eager for performance enhancements and innovative features, I’ve taken the time to dissect the changes and present them to you in a detailed manner. So, let’s embark on this journey and see how Docker Desktop is revolutionizing our containerized development experience.


2023: Docker Desktop’s Performance Revolution#

The 2023 iteration of Docker Desktop isn’t just an update; it’s a transformation. Here’s a deeper dive into the enhancements:

1. Docker Daemon Startup Time#

Docker Desktop’s startup times have seen significant improvements, with some configurations achieving initialization in just over 5 seconds. This optimization ensures that developers can dive into their containerized projects without delay.

Mac amd64Mac arm64Win amd64Linux amd64
Time7.84 s5.24 s19.1 s9.50 s

2. Container Operations with Hyperfine#

Using the hyperfine tool, I benchmarked Docker’s performance across versions. The results? Docker Desktop v4.22 consistently outperforms v4.11, showcasing the strides made in container operation efficiency.

To install Hyperfine you can use the command:

Terminal window
brew install hyperfine

Utilizing the hyperfine Tool#

To benchmark Docker commands, we’ll use the hyperfine tool. Here’s how you can execute it:

Terminal window
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'

Breaking Down the Command:

  • -i allows hyperfine to execute the benchmark in an interactive mode, providing real-time results.

  • -p specifies the warmup and benchmark commands for hyperfine.

  • The warmup command, docker stop ubuntu || :, instructs Docker to halt the ubuntu container if it’s active. If not, it simply proceeds without any action.

  • The benchmark command, docker run -it --rm ubuntu echo, prompts Docker to initiate the ubuntu container interactively and subsequently display the current date and time.

Results for Docker Desktop v4.22#

First Attempt:

Terminal window
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
Terminal window
Benchmark 1: docker run -it --rm ubuntu echo
Time (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 runs
Warning: Ignoring non-zero exit code.

Second Attempt:

Terminal window
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
Terminal window
Benchmark 1: docker run -it --rm ubuntu echo
Time (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 runs
Warning: Ignoring non-zero exit code.

Third Attempt:

Terminal window
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
Terminal window
Benchmark 1: docker run -it --rm ubuntu echo
Time (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 runs
Warning: Ignoring non-zero exit code.

From the First Attempt, we discern an average execution time of 44.3 milliseconds, accompanied by a deviation of 3.3 milliseconds. This suggests that the majority of runs were completed between 41.0 milliseconds and 47.6 milliseconds. The runs varied from a brisk 39.7 milliseconds to a peak of 49.6 milliseconds.

In the Second Attempt, the average execution time was 46.3 milliseconds, with a deviation of 2.3 milliseconds. This indicates that most runs were executed between 44.0 milliseconds and 48.6 milliseconds. The fastest run was recorded at 43.1 milliseconds, while the longest took 52.5 milliseconds.

For the Third Attempt, the average execution time stood at 46.5 milliseconds, with a more pronounced deviation of 5.3 milliseconds. This means that the bulk of runs were executed between 41.2 milliseconds and 51.8 milliseconds. The runs ranged from a swift 39.0 milliseconds to a high of 63.5 milliseconds.

Results for Docker Desktop v4.11#

First Attempt:

Terminal window
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
Terminal window
Benchmark 1: docker run -it --rm ubuntu echo
Time (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 runs
Warning: Ignoring non-zero exit code.

Second Attempt:

Terminal window
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
Terminal window
Benchmark 1: docker run -it --rm ubuntu echo
Time (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 runs
Warning: Ignoring non-zero exit code.

Third Attempt:

Terminal window
hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
Terminal window
Benchmark 1: docker run -it --rm ubuntu echo
Time (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 runs
Warning: Ignoring non-zero exit code.

From the First Attempt, we note an average execution time of 59.7 milliseconds, with a deviation of 3.2 milliseconds. This suggests that most runs were completed between 56.5 milliseconds and 62.9 milliseconds. The quickest run was at 55.0 milliseconds, while the longest took 68.3 milliseconds.

For the Second Attempt, the average execution time was 56.7 milliseconds, with a deviation of 2.7 milliseconds. This indicates that the majority of runs fell between 54.0 milliseconds and 59.4 milliseconds. The runs ranged from a swift 51.7 milliseconds to a peak of 62.5 milliseconds.

In the Third Attempt, the average execution time stood at 59.8 milliseconds, with a deviation of 4.5 milliseconds. This means that most runs were executed between 55.3 milliseconds and 64.3 milliseconds. The fastest run was recorded at 51.2 milliseconds, while the slowest reached 69.5 milliseconds.

Final Results (Docker Desktop 4.11 vs 4.22)#

Docker Desktop v4.11Docker Desktop v4.22
First Attempt55.0 - 68.3 ms39.7 - 49.6 ms
Second Attempt51.7 - 62.5 ms43.1 - 52.5 ms
Third Attempt51.2 - 69.5 ms39.0 - 63.5 ms

3. Resource Efficiency#

Docker’s new Resource Saver is nothing short of revolutionary. It intelligently manages resources, ensuring Docker only uses what it needs. This dynamic resource allocation ensures our Mac remains responsive, even during peak workloads.

To witness this functionality firsthand, initiate Docker Desktop and let it remain inactive for 30 seconds without any active containers. An icon will manifest in your whale menu and the Docker Desktop dashboard’s sidebar, signaling that the Resource Saver mode has been enabled.

Docker Desktop's Performance Odyssey Over a Year of Innovations - Step 1

The Resource Saver feature in Docker Desktop keeps an eye on container activity. If Docker Desktop remains inactive with no containers in operation for a span of 30 seconds, it autonomously diminishes its memory and CPU usage.

The following chart illustrates the influence of Resource Saver on the memory usage of all Docker Desktop processes, as gauged using the footprint CLI command. This command is designed to collect memory data about a specific process or a group of processes.

Docker Desktop's Performance Odyssey Over a Year of Innovations - Step 2


4.1 File Sharing with VirtioFS#

File sharing has always been a pain point in containerized development. However, with the integration of VirtioFS, Docker Desktop has made significant leaps in file I/O operations. This means faster builds, quicker data transfers, and an overall smoother development experience.

Types of File Sharing Mechanism#

File Sharing MechanismDescriptionAdditional Notes
VirtioFSA 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 FUSEUses 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-grpcfuseUtilizes the qemu hypervisor for file sharing. It’s the slowest mechanism but viable for building Redis images.
hyperkit-grpcfuseEmploys the hyperkit hypervisor for file sharing. Its speed is comparable to qemu-grpcfuse.
osxfsA 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#

In Docker Desktop settings, navigate to the “General” tab. Locate the section titled “Choose file sharing implementation for your containers” and select “VirtioFS”. Then, click on the “Apply & Restart” button.

Docker Desktop's Performance Odyssey Over a Year of Innovations - Step 3

Steps to Set Up and Test VirtioFS#

Create a directory using the command:

Terminal window
mkdir data

Populate the Directory with a Large Data File (1GB of random data) using the command:

Terminal window
dd if=/dev/zero of=data/data.img bs=1M count=1000

Next, 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:

Terminal window
docker build -t virtiofs-demo:latest .

Run the Docker Container using the command:

Terminal window
docker run -it --rm -v "$(pwd)/data:/data" virtiofs-demo

List the Running Containers using the command:

Terminal window
docker ps

Expected output:

Terminal window
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e47eb4731c80 virtiofs-demo "bash" 5 minutes ago Up 5 minutes gifted_lichterman

Next, measure File Copy Time into the Container

Terminal window
time docker cp gifted_lichterman:/data/data.img data/data.img

Expected result:

Terminal window
Successfully copied 1.05GB to /Users/ajeetsraina/july/virt/data/data.img
docker cp gifted_lichterman:/data/data.img data/data.img 0.61s user 1.84s system 36% cpu 6.750 total

Performance Comparison#

Comparing Docker Desktop 4.22 vs 4.11 (without VirtioFS enabled)

Data Size: 10GB Data TransferDocker Desktop v4.11Docker Desktop v4.22
Run #17 min 13.21 s5 min 11.10 s
Run #26 min 47.89 s5 min 04.08 s
Run #37 min 04.75 s5 min 02.08 s

Comparing Docker Desktop 4.22 vs 4.11 (with VirtioFS enabled)

Data Size: 10GB Data TransferDocker Desktop v4.11Docker Desktop v4.22
Run #12 min 18.55 s1 min 04.44 s
Run #22 min 20.23 s1 min 06.21 s
Run #32 min 15.65 s1 min 05.39 s

4.2 Evaluating Docker Desktop’s File-Sharing Performance#

Performance optimization is at the heart of every software upgrade. With Docker Desktop, the transition between versions is not just about new features but also about refining the existing ones for better efficiency. The shift to gVisor from VPNKit has been a game-changer. With up to 5x faster container-to-host networking on macOS, tasks that were previously time-consuming, like package downloads, are now a breeze.

In this segment, we assess the duration required to construct a Redis image from its source, leveraging Docker Desktop’s file-sharing capabilities. The source is provided through bind mount, and we clock the time needed for its in-container construction.

Redis Build Process#

Terminal window
# !/bin/bash
rm -rf /tmp/redis
docker 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#

ParameterVirtioFSgRPC FUSEqemu-grpcfusehyperkit-grpcfuse
Redis Build2.78 min3.54 min6.68 min5.19 min

Docker Desktop's Performance Odyssey Over a Year of Innovations - Step 4

Postgres Build Process#

Before diving into the Postgres build process, it’s essential to understand the setup. The following script showcases the steps involved in setting up a Postgres network, initiating a server, and launching a pgbench client.

Terminal window
# !/bin/bash
IMG=postgres:alpine
NET=postgresnet
TESTDIR=/tmp/postgrestest/data
PGNAME=postgrestest
PGPASS=postgrespass
docker network rm -q $NET &>/dev/null
echo "Setting up postgres network..."
docker network create $NET
rm -rf $TESTDIR
mkdir -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/null
docker rm ${PGNAME} &>/dev/null
docker network rm -q $NET &>/dev/null

Postgres Build Performance#

Scenario4.11.14.22
Postgresql tps (transactions/s)1000 tps2600 tps

Docker Desktop version 4.22 significantly outperforms version 4.11.1 in terms of transactions per second (tps). The newer version achieves 2600 tps, which is more than double the 1000 tps of the older version.

The choice of file-sharing mechanism in Docker Desktop can have a substantial impact on build times. For tasks like building Redis images, VirtioFS offers the best performance.

Docker Desktop’s newer version (4.22) showcases a marked improvement in handling Postgres transactions, indicating optimizations or enhancements in this version.

While VirtioFS is the fastest for Redis builds, it’s essential to consider the specific needs and compatibility requirements of individual projects when choosing a file-sharing mechanism.

The significant jump in Postgres transaction performance from version 4.11.1 to 4.22 suggests that Docker Desktop’s newer versions come with substantial improvements, making upgrades worthwhile.


5. Container Networking Enhancements#

Docker Desktop’s 2023 updates have placed a significant emphasis on networking improvements. The result? Enhanced networking interactions on macOS, ensuring smoother connections between containers. This translates to faster data transfers, reduced latency, and an overall more efficient containerized environment.

One of the pivotal changes was the introduction of gVisor in place of VPNKit for container-to-host networking, starting from Docker Desktop 4.19, released in March 2023.

NOTE

In 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 user-space, lightweight sandboxed container runtime designed to enhance container security and performance. Its architecture, based on the Linux kernel but implemented in user space, offers a speed advantage over VPNKit, a kernel-based solution.

For users managing projects where containers communicate with external servers (e.g., downloading packages via npm install or apt-get), this performance boost is invaluable.

Enabling gVisor#

To ensure Docker Desktop uses gVisor by default, run the following command:

Terminal window
cat ~/Library/Group\ Containers/group.com.docker/settings.json | grep -i network

If you wish to revert to VPNKit, add “networkType”:“vpnkit” to your settings.json file.

Benefits of gVisor over VPNKit:

  • Performance: gVisor’s speed outpaces VPNKit, enhancing container performance.
  • Security: As a sandboxed runtime, gVisor offers better protection against vulnerabilities.
  • Resource Efficiency: gVisor consumes fewer resources than VPNKit, optimizing your Mac’s performance.

Networking Benchmarks#

Container to Container

Benchmarking Tool: iperf3/netperf

Terminal window
# !/bin/bash
IMG=dockerpinata/iperf3:2.1
NET=iperf3net
SERVER=iperf3server
CLIENT=iperf3client
docker rm -f $SERVER &>/dev/null
docker 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/null
docker network rm -q $NET &>/dev/null
PlatformSpeed
Mac amd6441.5 Gb/s
Mac arm6481.7 Gb/s
Win amd6446.1 Gb/s
Linux amd6456.3 Gb/s

Container to Host

Benchmarking Tool: iperf3/netperf

Terminal window
# !/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
PlatformSpeed
Mac amd64686 Mb/s
Mac arm641.50 Gb/s
Win amd64596 Mb/s
Linux amd641.62 Gb/s

Host to Container

Benchmarking Tool: iperf3/netperf

Terminal window
# !/bin/bash
IMG=dockerpinata/iperf3:2.1
SERVER=iperf3server
docker rm -f $SERVER &>/dev/null
echo "Starting iperf3 server..."
docker run --rm -d -p 5201:5201 --name=${SERVER} ${IMG} /usr/bin/iperf3 -s -1
echo "Starting iperf3 client..."
iperf3 -c localhost
docker rm -f $SERVER &>/dev/null
Scenario4.11.14.22
Container to Container60 Gb/s72 Gb/s
Host to Container420 Mb/s1.4 Gb/s
Container to Host/internet930 Mb/s18 Gb/s

6. Hardware Compatibility: Embracing Apple Silicon and Rosetta#

Docker’s forward-thinking approach is evident with the introduction of the Rosetta feature. It bridges the gap between Intel and Apple Silicon architectures, ensuring developers have a seamless experience regardless of their hardware choice.

Docker Desktop's Performance Odyssey Over a Year of Innovations - Step 5

This implies you can now skip the command:

Terminal window
docker run --platform=linux/amd64

Similar to observations with VirtioFS, we’ve recognized performance enhancements when utilizing Rosetta. A member from our community highlighted a 7x speed boost, especially when compared to the sluggish pace of executing the DB migration procedure.


The Journey Continues#

Docker Desktop’s evolution is a testament to the relentless pursuit of excellence by its developers. With each enhancement, Docker becomes more powerful, intuitive, and user-centric.

But this isn’t the end. The world of tech is ever-evolving, and Docker is sure to continue its trend of innovation. As developers and users of this fantastic tool, we’re in for an exciting journey ahead. Whether you’re a Docker aficionado or a newbie, I encourage you to dive deep into the latest version and experience the future of containerized development firsthand.

Happy coding, and until next time, keep containerizing!


Social Channels#


Community of IT Experts#


Is this content AI-generated?

No. Every article on this blog is written by me personally, drawing on decades of hands-on IT experience and a genuine passion for technology.

I use AI tools exclusively to help polish grammar and ensure my technical guidance is as clear as possible. However, the core ideas, strategic insights, and step-by-step solutions are entirely my own, born from real-world work.

Because of this human-and-AI partnership, some detection tools might flag this content. You can be confident, though, that the expertise is authentic. My goal is to share road-tested knowledge you can trust.

Docker Desktop's Performance Odyssey Over a Year of Innovations
https://www.heyvaldemar.com/docker-desktops-performance-odyssey-over-a-year-of-innovations/
Author
Vladimir Mikhalev
Published at
2023-08-16
License
CC BY-NC-SA 4.0