13

I'm running a node.js application from within a docker container. I'm trying to retrieve system usage metrics of the container the node.js application is running inside of. Right now I'm using https://www.npmjs.com/package/dockerstats but it consistently shows no cpu or memory usage, running docker stats shows usage in each.

My code resembles the following:

let dockerId = setUp.getDockerId(); dockerId.then(dockerId => { if (dockerId !== null) { console.log(`dockerId: ${dockerId}`); dockerstats.dockerContainerStats(dockerId, data => { console.log(`cpu_percent: ${data.cpu_percent}`); console.log(`memPercent: ${data.memPercent}`); console.log(`memUsage: ${data.memUsage}`); }); } }); 

The setUp class resembles the following and uses https://www.npmjs.com/package/docker-container-id:

const getId = require('docker-container-id'); module.exports = class setUp { getDockerId () { return getId().then(id => { if (!id) { return null; } return id; }); } } 
2
  • 1
    Since a Docker container (usually) runs a single process under your control, and the "container" doesn't have much beyond that, poking around in /proc/self or /proc/1 inside the container might give you the information you need with relatively little privilege. Commented Jul 9, 2018 at 21:57
  • @DavidMaze So the docker container, has a /proc/self or /proc/1 already in its file system? For the solution I'm working on, I was going to mount /proc/stat and the cpuacct.usage found in the cgroup for the container and read from those. Commented Jul 10, 2018 at 16:48

2 Answers 2

36

As you said, you are using the docker-container-id package to obtain the container ID. This package works by inspecting the /proc/self/cgroup file, thus it should work only from inside the container (i.e. only when getContainerId() is executed from the containerized process). That said, further I will assume that you are trying to obtain the metrics from inside the container where your application runs (you did not mentioned this fact explicitly).

The problem here is that, as stated in the dockerstats package description, this package uses Docker API and, as per package source, the client connects to the docker socket (/var/run/docker.sock), which is is not available inside the container by default. The easy (but dangerous) way to workaround this is to mount host's /var/run/docker.sock into the container by using the following option when starting the container:

-v /var/run/docker.sock:/var/run/docker.sock 

E.g.

docker run -v /var/run/docker.sock:/var/run/docker.sock $MY_IMAGE_NAME 

However, this is STRONGLY DISCOURAGED, as it creates a serious security risk. Never do this in production. By doing so, you are allowing your container to control Docker, which is essentially the same as giving the container root access to the host system.

But you actually don't need to use the Docker API to access resource consumption metrics. The point is that you may directly read the information about process' cpuacct and memory control groups (which are responsible for tracking and limiting the CPU and the memory consumption respectively) from /sys/fs/cgroup. For example, reading the /sys/fs/cgroup/memory/memory.usage_in_bytes file will give you the amount of memory used by your container (in bytes):

# cat /sys/fs/cgroup/memory/memory.usage_in_bytes 164823040 

And reading the /sys/fs/cgroup/cpuacct/cpuacct.usage file will give you a total CPU usage of your container (in nanoseconds):

# cat /sys/fs/cgroup/cpuacct/cpuacct.usage 2166331144 

So, you can read these metrics from your application and process them. Also you may use statistics from procfs, refer to this discussion for details.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi @danila, Is there any way to collect system-level logs of containers from outside container (host)?
What do you mean by "system-level logs"? Containers run on the host's kernel, so kernel logs are not container-scoped. As to the userspace logs, the typical Docker pattern (more or less) is to run a single process inside the container and make this process to write any logs to stdout/stderr (which are read by container runtime itself, and you should not do this by hands. Instead, get the container logs from Docker). If you are not doing this (run many processes or even an init system inside the container), you are doing something non-trivial and should already be aware of what you are doing.
I mean vmstat, netstat, iostat, disk usage, dmesg, ps, etc...
19

As I do not have enough reputation to comment, I would like to complement the answer from @danila-kiver with a quick way to check the memory usage in Megabytes:

cat /sys/fs/cgroup/memory/memory.usage_in_bytes | awk '{ byte =$1 /1024/1024; print byte " MB" }'

Or in Gigabytes:

cat /sys/fs/cgroup/memory/memory.usage_in_bytes | awk '{ byte =$1 /1024/1024/1024; print byte " GB" }'

For anyone in need.

1 Comment

/1024 would be Mebibytes not Mb.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.