Limit resources used by Docker

For many years now, I am using Docker for my local development environment. In the beginning I was using my own custom images, but lately I’m mainly using “abstractions” like DDEV or wp-env, especially when working with WordPress projects. I run those mainly on Linux, but also have a setup on a Windows dual boot machine.

My previous Linux work laptop was only a Core i5-7200U dual-core with 16GB of RAM. Since I sometimes worked on different projects at the same time, my machine was on its limit pretty fast, with multiple PhpStorm instances and Chrome browser tabs open. Checking the resources, it became clear, that Docker was the issue, taking 50% of all resources.

Measuring resources used by Docker

Different operating systems have different tools to measure the running processes. If you want to find out, which process if using how much, you usually use them. But there is also a command build into Docker itself: docker stats. With this command, you get an output like this:

$ docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
NAME                                                 CPU %     MEM USAGE / LIMIT
34774832e449e0c5323d0c6eb5b88fdf-tests-cli-1         0.00%     628KiB / 15.01GiB
34774832e449e0c5323d0c6eb5b88fdf-cli-1               0.00%     1.133MiB / 15.01GiB
34774832e449e0c5323d0c6eb5b88fdf-tests-wordpress-1   0.01%     15.95MiB / 15.01GiB
34774832e449e0c5323d0c6eb5b88fdf-wordpress-1         0.00%     16.63MiB / 15.01GiB
34774832e449e0c5323d0c6eb5b88fdf-tests-mysql-1       0.02%     180.4MiB / 15.01GiB
34774832e449e0c5323d0c6eb5b88fdf-mysql-1             0.02%     183.1MiB / 15.01GiB
ddev-router                                          0.82%     43.99MiB / 15.01GiB
ddev-theme-tests-web                                 0.03%     144.4MiB / 15.01GiB
ddev-theme-tests-db                                  0.11%     150.6MiB / 15.01GiB
ddev-ssh-agent                                       0.32%     5.805MiB / 15.01GiB
ddev-theme-tests-dba                                 0.01%     20.1MiB / 15.01GiB

Changing the resource limits in WSL2

This is an example taken from within a WSL2 Docker setup. You can see two projects running with their containers. The “MEM USAGE” column also shows you the “LIMIT” all containers can take. On this machine with 32GB of RAM, it’s 50% of the available memory.

This limitation is set by WSL itself. By default, it takes 50% of the available memory or 8GB, whichever is less. On older builds however (before 20715), it was taking up to 80% of the memory! This can bring even powerful machines down easily.

Fortunately, it’s quite easy to overwrite this. All you have to do is create a .wsconfig file in your user’s home directory (%UserProfile%). Here, you create a file with the following content:

[wsl2]
memory=8G

Now you have to restart WLS2 with the following command (in Windows CMD or PowerShell), which will shut down all running distros, so make sure this is OK on your environment:

wsl --shutdown

Docker for Windows will now probably report, that Docker was stopped, and you can hit the “Restart” button. Now running the docker stats command again, you should only see a 8GB memory limit. There are more settings you can overwrite in that .wslconfig file, like the number of processors used. Since the virtual server, this blog is hosted, also only has 4GB of RAM, the 8GB I have defined here is still very generous.

Limiting the resources in other operating systems

I don’t use a Mac, so I can’t tell you how to change the settings there. And on Linux, there are many different options to achieve the same. It would be a bit too much to name all the different variants. But I do have a tip for those of you using Linux.

Limiting the resources per project

Instead of limiting the resources globally, you can limit them per container or for a project using docker-compose.yml files. When running a container manually, you can pass the resources into the call. But with a docker-compose.yml file, you can also set them for an individual service, like this, in which I’ve edited the file for the wp-env project:

version: '3.7'
services:
  mysql:
    image: mariadb
    deploy:
      resources:
        limits:
          memory: 2GB
# ...

Using the resources key, you can change different values for each service. With this change applied, the stats now look like this:

$ docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
NAME                                                 CPU %     MEM USAGE / LIMIT
34774832e449e0c5323d0c6eb5b88fdf-cli-1               0.00%     576KiB / 7.761GiB
34774832e449e0c5323d0c6eb5b88fdf-wordpress-1         0.01%     15.87MiB / 7.761GiB
34774832e449e0c5323d0c6eb5b88fdf-mysql-1             0.02%     177.6MiB / 2GiB
34774832e449e0c5323d0c6eb5b88fdf-tests-cli-1         0.00%     2.664MiB / 7.761GiB
34774832e449e0c5323d0c6eb5b88fdf-tests-wordpress-1   0.00%     16.17MiB / 7.761GiB
34774832e449e0c5323d0c6eb5b88fdf-tests-mysql-1       0.03%     86.56MiB / 7.761GiB

As you can see, all services use the previously defined 8GB, but the MySQL service is limited to 2GB now. As the MySQL service is usually the one using the most memory, this is the service I would recommend limiting first.

Conclusion

This is not a blog post on how to optimize the resources for Docker containers in all operating systems and in all different scenarios. But I hope it gives you an idea on the options and helps you, you quickly limit them on a machine with a low amount of total RAM or one few processors/threads. For my old work laptop, it really helped, and I was able to get work done a lot faster, as the other processes didn’t have to share the remaining 50% of memory.

Posted by

Bernhard is a full time web developer who likes to write WordPress plugins in his free time and is an active member of the WP Meetups in Berlin and Potsdam.

Leave a Reply

Your email address will not be published. Required fields are marked *