Docker build --ulimit flag has no effect
Asked Answered
K

3

5

My docker builds are failing because of a file handle limit error. They crash out with

Error: EMFILE: too many open files

when I check ulimit -n on the container I see

-n: file descriptors 1024

So I pass the following flags to my build command

docker build --ulimit nofile=65536:65536 -t web .

but this does not change anything, my container still shows

-n: file descriptors 1024

No matter what I do I dont seem to be able to get that ulimit file descriptor limit to change.

What am I doing wrong here?

Kharif answered 20/9, 2018 at 6:11 Comment(0)
K
6

So, I discovered the cause. Posting the answer incase anyone else is having the same issue as I just wasted most of a day on this. I have been debugging a very long running build and have been using

export DOCKER_BUILDKIT=1

to enable some extended build information. Very useful timings etc, although it appears as though enabling DOCKER_BUILDKIT completely ignores ulimit flags passed to the docker build command.
When I set

export DOCKER_BUILDKIT=0

it works. So long story short, avoid using buildkit with ulimit params

Kharif answered 20/9, 2018 at 7:25 Comment(0)
E
4

I wrote a simple test and it seams to work fine on Docker 18.06

> $ docker -v
Docker version 18.06.1-ce, build e68fc7a

I created a Dockerfile like this:

FROM alpine
RUN ulimit -n > /tmp/ulimit.txt

And then:

> $ docker build --ulimit nofile=65536:65536 .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM alpine
 ---> e21c333399e0
Step 2/2 : RUN ulimit -n > /tmp/ulimit.txt
 ---> Running in 1aa4391d057d
Removing intermediate container 1aa4391d057d
 ---> 18dd1953d365
Successfully built 18dd1953d365

docker run -ti 18dd1953d365 cat /tmp/ulimit.txt
65536

> $ docker build --ulimit nofile=1024:1024 --no-cache .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM alpine
 ---> e21c333399e0
Step 2/2 : RUN ulimit -n > /tmp/ulimit.txt
 ---> Running in c20067d1fe10
Removing intermediate container c20067d1fe10
 ---> 134fc7252574
Successfully built 134fc7252574

> $ docker run -ti 134fc7252574 cat /tmp/ulimit.txt
1024
Eiffel answered 20/9, 2018 at 6:57 Comment(1)
Thank you for testing that.. I discovered what was happening and posted the solution above.Kharif
H
1

When using the BuildKit, docker seems to execute the command in the systemd unit context of the daemon the has the ulimit.

I used the Dockerfile to test:

> cat <<EOF >Dockerfile
FROM alpine
RUN echo -e "\n\n-----------------\nulimit: $(ulimit -n)\n-----------------\n\n"
EOF

Check first the actual limit values for docker service:

> systemctl show docker.service | grep LimitNOFILE
LimitNOFILE=infinity
LimitNOFILESoft=infinity

The values set inside running container is 1048576:

> docker run -it --rm alpine sh -c "ulimit -n"
1048576

The values set inside BuildKit build is 1073741816:

> DOCKER_BUILDKIT=1 docker build --progress=plain --no-cache .
#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 195B done
#2 DONE 0.0s

#1 [internal] load .dockerignore
#1 transferring context: 2B done
#1 DONE 0.0s

#3 [internal] load metadata for docker.io/library/alpine:latest
#3 DONE 0.0s

#5 [1/2] FROM docker.io/library/alpine
#5 CACHED

#4 [2/2] RUN echo -e "\n\n-----------------\nulimit: $(ulimit -n)\n--------...
#4 0.452
#4 0.452
#4 0.452 -----------------
#4 0.452 ulimit: 1073741816
#4 0.452 -----------------
#4 0.452
#4 0.452
#4 DONE 0.5s

#6 exporting to image
#6 exporting layers 0.0s done
#6 writing image sha256:facf7aee0b81d814d5b23a663e4f859ec8ba54d7e5fe6fdbbf8beacf0194393b done
#6 DONE 0.0s

Configure the docker.service to set a different default value (LimitNOFILE=1024) that will be also used by BuildKit (be careful not to overwrite an existing file):

> mkdir -p /etc/systemd/system/docker.service.d
> cat <<EOF >/etc/systemd/system/docker.service.d/service.conf.ok
[Service]
LimitNOFILE=1024
EOF
> systemctl daemon-reload
> systemctl restart docker.service

The values set inside running container remains unchanged to 1048576:

> docker run -it --rm alpine sh -c "ulimit -n"
1048576

The values set inside BuildKit build is now 1024:

> DOCKER_BUILDKIT=1 docker build --progress=plain --no-cache .
#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 195B done
#2 DONE 0.0s

#1 [internal] load .dockerignore
#1 transferring context: 2B done
#1 DONE 0.0s

#3 [internal] load metadata for docker.io/library/alpine:latest
#3 DONE 0.0s

#5 [1/2] FROM docker.io/library/alpine
#5 CACHED

#4 [2/2] RUN echo -e "\n\n-----------------\nulimit: $(ulimit -n)\n--------...
#4 0.452
#4 0.452
#4 0.452 -----------------
#4 0.452 ulimit: 1024
#4 0.452 -----------------
#4 0.452
#4 0.452
#4 DONE 0.5s

#6 exporting to image
#6 exporting layers 0.0s done
#6 writing image sha256:7e40c8a8d5f0ca8f2b2b53515f11f47655f6e1693ffcd5f5a118402c13a44ab4 done
#6 DONE 0.0s
Henden answered 4/6, 2020 at 20:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.