Weird _SC_OPEN_MAX value

Hi,

During my investigations on why a software that I used to run inside a docker container can’t launch anymore, I have noticed a strange behavior.
Indeed, the value of the _SC_OPEN_MAX value goten from inside of my container is very large on one of my host.
I have made a try on two hosts with the same docker engine version: 23.0.1, build a5ee5b1dfc.
The same container on the two hosts gives very different values:
- 1073741816 on the first,
- 1048576 on the second.

The software uses the value of this variable to allocate an array of 16 bits object.
The first device has 2 Go RAM, hence 1073741816 * 16 = 17179869056 bits, which is slightly more than 2 Go. The program crashes because of a std::bad_alloc.
On the second device, which has 24 Go RAM, the values is way low, and no crash.

Why is there such a difference in the value between the two hosts ?

You posted your question in the Docker DEsktop for Linux category. Are you running Docker Desktop or just Docker CE (Docker Engine)? BAsed on the version number I guess Docker CE

You guessed right, I encounter the issue in docker engine. Sorry for the mistake, I had a hard time finding the right place for my thread. Could you please indicate it, then ?
Thanks for your help.

I moved the topic the the “DockerEngine” category.

I don’t know, but if I am not mistaken, that is a kernel setting which will be the same in each container since containers are running on top of the kernel of the host. The “same container” will never be the same container on different hosts, only a similar container with the same parameters based on the same image. I am pretty sure you knew that, I just wanted to clarify it in case someone reads this topic.

What is “Go”? Do you mean Gi (GigaByte/GibiByte)?

I don’t know, but if I am not mistaken, that is a kernel setting which will be the same in each container since containers are running on top of the kernel of the host. The “same container” will never be the same container on different hosts, only a similar container with the same parameters based on the same image. I am pretty sure you knew that, I just wanted to clarify it in case someone reads this topic

Thanks for the clarification. By same container I meant same image. What I don’t understand is that if I compile and run the following code:

#include <unistd.h>
#include <iostream>

int main()
{
    std::cout << sysconf(_SC_OPEN_MAX) << std::endl;
}

on any of my two hosts, I get 1024 as output for both.

I believed that docker containers and hosts share the same kernel but the values on bare host and inside containers are different. Basically, a 1024 value would likely not result in a std::bad_alloc exception.
Also, this value has probably changed since the container used to work as-is.
I realize that I have omitted some crucial informations in my question.

What is “Go”? Do you mean Gi (GigaByte/GibiByte)?

So sorry for that, this acronym comes from my native language. It stands for GibiB.

Thanks for your help

Thank you for the C++ code. I almost never write C++ code so it helps a lot when I get a working code to try. Using that I did some research to understand these parameters a little bit better.

It looks like you were right. I knew SC_OPEN_MAX was similar to the kernel variable fs.file-max and I assumed they were the same. It seems I was wrong. In fact SC_OPEN_MAX is the value that you can also get by using ulimit -n. It is a process level setting. Since a container is an isolated process, you can get a different value in a container and on the host.

In my test VM I tried this to demonstrate:

docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp gcc:4.9 g++ -o myapp myapp.c
docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp gcc:4.9 ./myapp
# output: 1048576
docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp gcc:4.9 bash -c 'ulimit -n'
# output: 1048576

./myapp
# output: 1024
ulimit -n
# output: 1024

The maximum value of the open files at process level can be changed by using ulimit and the docker run command also has an “ulimit” parameter to change this value.

docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp --ulimit nofile=300:300 gcc:4.9 ./myapp
# output: 300
docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp --ulimit nofile=300:300 gcc:4.9 bash -c 'ulimit -n'
# output: 300

If you want to change the default value, the Docker daemon has paramaters to do that. Either by using the dockerd command or by using the following config file at /etc/docker/daemon.json and restarting the docker daemon.

{
  "default-ulimits": {
    "nofile": {
      "Hard": 64000,
      "Name": "nofile",
      "Soft": 64000
    }
  }
}

After this you would get this:

docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp gcc:4.9 ./myapp
# output: 64000
docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp gcc:4.9 bash -c 'ulimit -n'
# output: 64000

I am not sure why it is dfferent on one of your machines. I can only guess like

  • Even though you has the same version number of the Docker engine on the two hosts, you could have installed Docker differently. For example on one host you used snap, on another you followed the official documentation, or you could have also installed Docker from Ubuntu’s own repository, but in these cases the version number should be different.
  • It is also possible that on one host you ae using rootful Docker (installed system-wide) and on the other you have rootless Docker (available only for one user) so these daemons can have different values. If you acidentally change the context you use a different daemon

If anything is installed differently, different updates can be applied or at least not the same time, so one could lose the modified setting after an upgrade while the other doesn’t.

The second is the same as on my machine. So the first might have a different daemon configuration.

What you can try

  • Check /etc/docker/daemon.json
  • Check the parameters of dockerd
    sytemctl status dockerd
    
  • Check the output of
    docker info
    
    and
    docker version
    
    which can give you some idea about the differences if there is any. (You have probably done that already)
  • Check the docker context
    docker context ls
    
    But this can also be seen in the output of docker info

I hope this helps more than my previous answer :slight_smile:

Thanks for your detaileld response, I managed to get my software back to work by overriding in my docker-compose the values you hinted for ulimit.

I am not sure why it is dfferent on one of your machines. I can only guess like

  • Even though you has the same version number of the Docker engine on the two hosts, you could have installed Docker differently. For example on one host you used snap, on another you followed the official documentation, or you could have also installed Docker from Ubuntu’s own repository, but in these cases the version number should be different.
  • It is also possible that on one host you ae using rootful Docker (installed system-wide) and on the other you have rootless Docker (available only for one user) so these daemons can have different values. If you acidentally change the context you use a different daemon

If anything is installed differently, different updates can be applied or at least not the same time, so one could lose the modified setting after an upgrade while the other doesn’t.

Indeed, on the two hosts docker has been installed differently: on the main one, with the package manager (the distro is Archlinux) and on the second one via docker desktop since this is a Windows host. I have tweaked the WSL to call the docker-desktop software.

I am afraid we won’t get the final word, though. Why these values suddenly changed, making the software stop working ?

Anyway, thanks for your support, very appreciated.

It was my very first thought until you shared the version number and wrote this

Docker Desktop still runs Docker CE 20.10 unless some beta or experimental features are enabled like wasm, if I remember correctly.

And due to the fact that Docker desktop runs everything inside the virtual machine, it can even have completely different kernel settings too. Depending on the Docker Destkop settings and/or version these kernel parameters could be different although I have never checked it and the Docker daemon configuration could also change because of a different setting or a Docker Desktop update. It could have also been a bug. Since you mentioned WSL, if you run Docker Desktop on Windows, you can search for bug reports here

or report a new issue if you still want to find out why it happened…

I am afraid that I have badly explained myself.

The error appears when I run a container in my linux environment. The Windows side, despite running docker inside a VM with somehow different settings, as you said, works fine with the software, because _SC_OPEN_MAX is not very big.

The question I am asking is why my linux docker host that has behad fine for more than five years without need to override the ulimit setting suddenly requires it.

It looks like you were right. I knew SC_OPEN_MAX was similar to the kernel variable fs.file-max and I assumed they were the same. It seems I was wrong. In fact SC_OPEN_MAX is the value that you can also get by using ulimit -n. It is a process level setting. Since a container is an isolated process, you can get a different value in a container and on the host.

By the way, could you hint me where you found these solving informations ?

Many thanks for your help

I tried to search for it, read multiple documentations and Google results, but eventualyl I asked ChatGPT. It gave me incorrect answers but I corrected it and pointed out why that can’t be true so it regenerated the answer and it gave me some ideas so eventually I tried the command above which confirmed what I stated in my previous post. sysctl fs.file-max always gave me the same output in the container and on the host, but ulimit didn’t. I knew about ulimit, but not enough to give you an answer without some test command.

This is why I haven’t shared any links because it was not one link that explained it to me.

There is one link I can share but that is about ulimit vs fs.file-max: linux - How do ulimit -n and /proc/sys/fs/file-max differ? - Server Fault

Sorry, I don’t have all the links, because none of those were actual answers just clues and I didn’t save them. I could find the above link by searching again and noticing the already visited site in the Google search result.