TCM
TCM

Reputation: 11

Determining the Docker for Mac RAM limit from Node

Background

We are using Docker for Mac. Docker/Linux Containers can't run natively on MacOS/Darwin/Unix, so internally Docker for Mac runs a Linux virtual machine, and all of the containers actually run on that.

Docker for Mac has a GUI settings interface that lets us specify the RAM that is allocated to this Linux virtual machine (screenshot). It seems to default to 2 GB, but our development environment has a practical minimum of 8 GB or else we encounter pathological swapping and the Docker daemon may become unresponsive.

Our problem is that the RAM limit seems to sometimes be silently reset to this default. This seems to happen after automatic updates, but not consistently. Our team members don't always realize what has happened, and often waste time investigating other causes of their performance issues before finding the real cause.

Question

We use a Node script to spin up most of our local development environment. How can I detect the current RAM limit in Docker for Mac from Node, so that our script can display a warning message to our developers if it's below our expected minimum?

Attempted Solution

I haven't found any docker commands that directly expose this setting, but the docker stats command reports the memory usage for each running container, and their individual RAM limits appear to be the same as I've set for Docker for Mac overall.

docker stats --no-stream --format "{{.MemUsage}}"
172MiB / 7.786GiB
175.6MiB / 7.786GiB
171.7MiB / 7.786GiB
1.031MiB / 7.786GiB

I have been working on parsing the value out of this.

const execa = require('execa');

(async () => {
  const result = await execa(
    'docker',
    ['stats', '--no-stream', '--format', '{{.MemUsage}}'],
    {encoding: 'utf8'}
  );
  const stdout = await result.stdout;
  const firstLine = stdout.split(/\n/)[0];
  const limit = firstLine.split(/ \/ /)[1];
  console.log(limit); // 7.786GiB
})();

However, this has a major limitation: it only works if there is a container currently running. I would like to use this to warn users before starting any containers. It's also inconvenient that the result is formatted for humans, with a potentially-variable unit suffix.


Is there any good way to detect the Docker for Mac RAM limit setting from Node?

Upvotes: 1

Views: 394

Answers (2)

TCM
TCM

Reputation: 11

The settings for Docker for Mac are stored in a simple JSON file at ~/Library/Group Containers/group.com.docker/settings.json. The RAM limit is specified as an integer under the 'memoryMiB' key. We can read this from Node like this:

const fs = require('fs');
const os = require('os');
const path = require('path');

(() => {
  const configPath = path.join(
    os.homedir(),
    "Library/Group Containers/group.com.docker/settings.json"
  );

  const config = JSON.parse(fs.readFileSync(configPath, {
    encoding: 'utf8'
  }));

  if (typeof config.memoryMiB === 'number' && config.memoryMiB < 8000) {
    console.warn(
      `Docker for Mac is configured to use ${config.memoryMiB} MiB of RAM.`);
    console.warn(
      'Consider raising it to 8 GB or you may encounter performance issues.');
  }
})();

Upvotes: 0

David Maze
David Maze

Reputation: 158908

The “host’s” /proc filesystem is exposed into containers, so you can pretty straightforwardly check with:

docker run --rm busybox cat /proc/meminfo \
  | grep MemTotal

You can also find the SwapTotal setting there. These are technically Linux kernel values, but they mirror the VM settings in the Docker for Mac controls.

Upvotes: 1

Related Questions