Raise Docker open file limit at startup
Raise the runtime container soft nofile limit before supervisord starts so WebUI and managed services inherit a larger descriptor allowance. Add an explicit compose nofile example, document the startup contract, and cover the limit raise and hard-limit cap with focused regression tests.
Alessandro committed
Jun 24, 2026 at 11:00 UTC
68c31b51e1a786eb870700c8320628415c0ef8e0
4 files changed
+107
docker/run/AGENTS.md
+1
@@ -21,6 +21,7 @@
21
- Keep the two-runtime Python model aligned with the root contract.
22
- Do not bake secrets, local `.env` values, or user data into the image.
23
- Runtime startup must ensure `/a0/usr/uploads` exists before supervised services start.
24
+- Runtime startup raises the soft open-file limit toward `A0_NOFILE_LIMIT` (default `65535`) before supervisord starts, bounded by the container hard limit.
25
26
## Work Guidance
27
docker/run/docker-compose.yml
+4
@@ -6,5 +6,9 @@ services:
6
- ./agent-zero:/a0
7
ports:
8
- "50080:80"
9
+ ulimits:
10
+ nofile:
11
+ soft: 65535
12
+ hard: 65535
13
extra_hosts:
14
- "host.docker.internal:host-gateway"
docker/run/fs/exe/initialize.sh
+37
@@ -9,6 +9,43 @@ if [ -z "$1" ]; then
9
fi
10
BRANCH="$1"
11
12
+raise_open_file_limit() {
13
+ local requested="${A0_NOFILE_LIMIT:-65535}"
14
+ local soft
15
+ local hard
16
+ local target
17
+
18
+ if ! [[ "$requested" =~ ^[0-9]+$ ]] || [ "$requested" -lt 1 ]; then
19
+ echo "Warning: invalid A0_NOFILE_LIMIT='$requested'; keeping open file limit at $(ulimit -S -n)." >&2
20
+ return
21
+ fi
22
+
23
+ soft="$(ulimit -S -n)"
24
+ hard="$(ulimit -H -n)"
25
+
26
+ if [ "$soft" = "unlimited" ]; then
27
+ echo "Open file limit is already unlimited."
28
+ return
29
+ fi
30
+
31
+ target="$requested"
32
+ if [ "$hard" != "unlimited" ] && [ "$target" -gt "$hard" ]; then
33
+ target="$hard"
34
+ fi
35
+
36
+ if [ "$target" -gt "$soft" ]; then
37
+ if ulimit -S -n "$target"; then
38
+ echo "Raised open file soft limit from $soft to $(ulimit -S -n) (hard: $hard)."
39
+ else
40
+ echo "Warning: failed to raise open file soft limit from $soft to $target (hard: $hard)." >&2
41
+ fi
42
+ else
43
+ echo "Open file soft limit is $soft (target: $requested, hard: $hard)."
44
+ fi
45
+}
46
+
47
+raise_open_file_limit
48
+
49
# Copy all contents from persistent /per to root directory (/) without overwriting
50
cp -r --no-preserve=ownership,mode /per/* /
51
tests/test_docker_initialize_limits.py
new
+65
@@ -0,0 +1,65 @@
1
+import re
2
+import resource
3
+import subprocess
4
+from pathlib import Path
5
+
6
+import pytest
7
+
8
+
9
+REPO_ROOT = Path(__file__).resolve().parents[1]
10
+INITIALIZE_SCRIPT = REPO_ROOT / "docker" / "run" / "fs" / "exe" / "initialize.sh"
11
+
12
+
13
+def _raise_limit_function() -> str:
14
+ text = INITIALIZE_SCRIPT.read_text(encoding="utf-8")
15
+ match = re.search(r"^raise_open_file_limit\(\) \{\n.*?^\}\n", text, re.M | re.S)
16
+ assert match, "initialize.sh must define raise_open_file_limit"
17
+ return match.group(0)
18
+
19
+
20
+def _run_bash(script: str) -> subprocess.CompletedProcess[str]:
21
+ return subprocess.run(
22
+ ["bash", "-c", script],
23
+ check=True,
24
+ text=True,
25
+ capture_output=True,
26
+ )
27
+
28
+
29
+def test_initialize_raises_soft_open_file_limit_to_requested_target():
30
+ function = _raise_limit_function()
31
+
32
+ result = _run_bash(
33
+ f"""
34
+ set -euo pipefail
35
+ {function}
36
+ ulimit -S -n 1024
37
+ A0_NOFILE_LIMIT=4096
38
+ raise_open_file_limit
39
+ test "$(ulimit -S -n)" = "4096"
40
+ """
41
+ )
42
+
43
+ assert "Raised open file soft limit from 1024 to 4096" in result.stdout
44
+
45
+
46
+def test_initialize_caps_open_file_limit_at_hard_limit():
47
+ _soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
48
+ if hard != resource.RLIM_INFINITY and hard < 2048:
49
+ pytest.skip("host hard open-file limit is too low for this regression test")
50
+
51
+ function = _raise_limit_function()
52
+
53
+ result = _run_bash(
54
+ f"""
55
+ set -euo pipefail
56
+ {function}
57
+ ulimit -S -n 1024
58
+ ulimit -H -n 2048
59
+ A0_NOFILE_LIMIT=65535
60
+ raise_open_file_limit
61
+ test "$(ulimit -S -n)" = "2048"
62
+ """
63
+ )
64
+
65
+ assert "Raised open file soft limit from 1024 to 2048" in result.stdout