Docker build --ulimit 标志无效
Docker build --ulimit flag has no effect
我的 docker 构建由于文件句柄限制错误而失败。他们崩溃了
Error: EMFILE: too many open files
当我检查容器上的 ulimit -n 时,我看到了
-n: file descriptors 1024
所以我将以下标志传递给我的构建命令
docker build --ulimit nofile=65536:65536 -t web .
但这并没有改变任何东西,我的容器仍然显示
-n: file descriptors 1024
无论我做什么,我似乎都无法更改 ulimit 文件描述符限制。
我做错了什么?
我写了一个简单的测试,它在 Docker 18.06
上运行良好
> $ docker -v
Docker version 18.06.1-ce, build e68fc7a
我创建了一个 Dockerfile
这样的:
FROM alpine
RUN ulimit -n > /tmp/ulimit.txt
然后:
> $ 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
所以,我找到了原因。发布答案以防其他人遇到与我浪费了大部分时间的问题相同的问题。
我一直在调试一个很长的 运行 构建并且一直在使用
export DOCKER_BUILDKIT=1
启用一些扩展的构建信息。非常有用的计时等,尽管启用 DOCKER_BUILDKIT 似乎完全忽略了传递给 docker 构建命令的 ulimit 标志。
当我设置
export DOCKER_BUILDKIT=0
有效。长话短说,避免将 buildkit 与 ulimit params
一起使用
使用 BuildKit 时,docker 似乎在具有 ulimit 的守护进程的 systemd 单元上下文中执行命令。
我用Dockerfile
来测试:
> cat <<EOF >Dockerfile
FROM alpine
RUN echo -e "\n\n-----------------\nulimit: $(ulimit -n)\n-----------------\n\n"
EOF
首先检查 docker 服务的实际限制值:
> systemctl show docker.service | grep LimitNOFILE
LimitNOFILE=infinity
LimitNOFILESoft=infinity
在 运行 容器中设置的值是 1048576
:
> docker run -it --rm alpine sh -c "ulimit -n"
1048576
BuildKit 构建中设置的值是 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
配置 docker.service 以设置不同的默认值 (LimitNOFILE=1024),BuildKit 也会使用该默认值(注意不要覆盖现有文件):
> 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
运行容器内设置的值保持不变为1048576
:
> docker run -it --rm alpine sh -c "ulimit -n"
1048576
BuildKit 构建中设置的值现在是 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
我的 docker 构建由于文件句柄限制错误而失败。他们崩溃了
Error: EMFILE: too many open files
当我检查容器上的 ulimit -n 时,我看到了
-n: file descriptors 1024
所以我将以下标志传递给我的构建命令
docker build --ulimit nofile=65536:65536 -t web .
但这并没有改变任何东西,我的容器仍然显示
-n: file descriptors 1024
无论我做什么,我似乎都无法更改 ulimit 文件描述符限制。
我做错了什么?
我写了一个简单的测试,它在 Docker 18.06
上运行良好> $ docker -v
Docker version 18.06.1-ce, build e68fc7a
我创建了一个 Dockerfile
这样的:
FROM alpine
RUN ulimit -n > /tmp/ulimit.txt
然后:
> $ 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
所以,我找到了原因。发布答案以防其他人遇到与我浪费了大部分时间的问题相同的问题。 我一直在调试一个很长的 运行 构建并且一直在使用
export DOCKER_BUILDKIT=1
启用一些扩展的构建信息。非常有用的计时等,尽管启用 DOCKER_BUILDKIT 似乎完全忽略了传递给 docker 构建命令的 ulimit 标志。
当我设置
export DOCKER_BUILDKIT=0
有效。长话短说,避免将 buildkit 与 ulimit params
一起使用使用 BuildKit 时,docker 似乎在具有 ulimit 的守护进程的 systemd 单元上下文中执行命令。
我用Dockerfile
来测试:
> cat <<EOF >Dockerfile
FROM alpine
RUN echo -e "\n\n-----------------\nulimit: $(ulimit -n)\n-----------------\n\n"
EOF
首先检查 docker 服务的实际限制值:
> systemctl show docker.service | grep LimitNOFILE
LimitNOFILE=infinity
LimitNOFILESoft=infinity
在 运行 容器中设置的值是 1048576
:
> docker run -it --rm alpine sh -c "ulimit -n"
1048576
BuildKit 构建中设置的值是 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
配置 docker.service 以设置不同的默认值 (LimitNOFILE=1024),BuildKit 也会使用该默认值(注意不要覆盖现有文件):
> 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
运行容器内设置的值保持不变为1048576
:
> docker run -it --rm alpine sh -c "ulimit -n"
1048576
BuildKit 构建中设置的值现在是 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