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.

Key Performance Metrics Explored

To get a holistic view of the progress, I meticulously benchmarked Docker Desktop’s performance from 2022 to 2023 on macOS. Here are the parameters I considered:

  1. Docker Daemon Startup Time: This metric gauges the efficiency of Docker’s initialization process.

  2. Container Operations: A measure of the agility with which Docker handles container stop-start cycles.

  3. Idle Resource Efficiency: A critical metric for those who value system performance, this measures Docker’s CPU and memory footprint when idle.

  4. File Sharing Efficiency: As developers, file transfer speeds can make or break our workflow. This metric evaluates just that.

  5. Networking: In an interconnected world, data transfer rates are paramount. I looked at both inter-container and container-to-internet speeds.

  6. Hardware Compatibility: With the rise of Apple Silicon devices, it’s essential to know how Docker handles cross-architecture operations.

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 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

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:

brew install hyperfine

Utilizing 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'

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:

hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
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:

hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
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:

hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
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:

hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
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:

hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
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:

hyperfine -i -p 'docker stop ubuntu || :' 'docker run -it --rm ubuntu echo'
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.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

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

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

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 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 Utilizes 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

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

Steps to Set Up and Test VirtioFS

Create a directory using the command:

mkdir data

Populate 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=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:

docker build -t virtiofs-demo:latest .

Run the Docker Container using the command:

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

List the Running Containers using the command:

docker ps

Expected output:

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

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

Expected result:

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 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

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

#!/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

Parameter VirtioFS gRPC FUSE qemu-grpcfuse hyperkit-grpcfuse
Redis Build 2.78 min 3.54 min 6.68 min 5.19 min

Docker Desktop's Performance Odyssey Over a Year of Innovations

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.

#!/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

Scenario 4.11.1 4.22
Postgresql tps (transactions/s) 1000 tps 2600 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:

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

#!/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
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.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
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’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

This implies you can now skip the command:

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!

My Services

💼 Take a look at my service catalog and find out how we can make your technological life better. Whether it’s increasing the efficiency of your IT infrastructure, advancing your career, or expanding your technological horizons — I’m here to help you achieve your goals. From DevOps transformations to building gaming computers — let’s make your technology unparalleled!

Refill the Author’s Coffee Supplies

💖 PayPal
🏆 Patreon
💎 GitHub
🥤 BuyMeaCoffee
🍪 Ko-fi

Vladimir Mikhalev
I’m Vladimir Mikhalev, the Docker Captain, but my friends can call me Valdemar.

DevOps Community

hey 👋 If you have questions about installation or configuration, then ask me and members of our community: