Skip to content

File Descriptors leak in docker.from_env() on rootless Docker — File Descriptors accumulate in dockerd #3338

Open
@gavelight

Description

@gavelight

Summary
Calling docker.from_env() in a rootless Docker environment (UNIX socket: /run/user/1001/docker.sock) causes the number of open file descriptors (FDs) held by dockerd to continuously increase, even when the client is immediately discarded and the script terminates.

This FD leak is not observed in rootful Docker environments or when using the Docker CLI via subprocess.

Steps to Reproduce

  1. Run a clean rootless test container:
docker run -it --rm \
  --tmpfs /run \
  -v /run/user/1001/docker.sock:/run/user/1001/docker.sock \
  -e DOCKER_HOST=unix:///run/user/1001/docker.sock \
  python:3.12-slim /bin/bash
  1. Inside the container:
pip install docker
echo "import docker; docker.from_env()" > test_fd.py
  1. Run the script multiple times:
    for i in $(seq 1 100); do python test_fd.py; done

  2. Check FD count on host:
    lsof -w | grep dockerd | wc -l

The count increases with every run. Even when using .close(), the leak persists.

What We Tried

  • Confirmed .close() has no effect
  • Tested both:
    • `docker==5.0.3` with legacy stack (`urllib3==1.26.15`)
      
    • `docker==7.1.0` with `requests-unixsocket` and `urllib3==2.2.1`
      
  • Verified it does not leak in rootful Docker
  • Verified subprocess-based usage (docker ps) does not leak
  • Upgraded containerd from v1.7.1 → v1.7.27: still leaks

Environment
Docker Info

Client:
 Version:    24.0.4
 Context:    default
 Debug Mode: false

Server:
 Containers: 3
  Running: 1
  Paused: 0
  Stopped: 2
 Images: 44
 Server Version: 24.0.4
 Storage Driver: fuse-overlayfs
 Logging Driver: json-file
 Cgroup Driver: none
 Cgroup Version: 1
 Runtimes: io.containerd.runc.v2 runc
 containerd version: 1677a17964311325ed1c31e2c0a3589ce6d5c30d
 runc version: v1.1.7-0-g860f061
 Kernel Version: 4.18.0-372.9.1.el8.x86_64
 Operating System: Red Hat Enterprise Linux 8.6 (Ootpa)
 Docker Root Dir: /bb/cc/docker_data
 rootless: true

OS info

NAME="Red Hat Enterprise Linux"
VERSION="8.6 (Ootpa)"
ID="rhel"
VERSION_ID="8.6"
PLATFORM_ID="platform:el8"
PRETTY_NAME="Red Hat Enterprise Linux 8.6 (Ootpa)"

containerd version
containerd github.com/containerd/containerd v1.7.1 1677a17964311325ed1c31e2c0a3589ce6d5c30d

Python Environment

docker: 5.0.3 and 7.1.0 (tested both)

requests: 2.26.0 → 2.31.0

urllib3: 1.26.15 and 2.2.1

requests-unixsocket: 0.3.0 (used in 7.x only)

Python: 3.12.1

Rootless Docker Setup

  • Installed using Docker’s official script: dockerd-rootless-setuptool.sh install
  • Managed via: systemctl --user start docker
  • Docker socket path: unix:///run/user/1001/docker.sock
  • dockerd process runs under non-root user (UID 1001)
  • Verified environment variable: DOCKER_HOST=unix:///run/user/1001/docker.sock
  • rootlesskit version: 1.1.0

Workaround
Using the Docker CLI via subprocess avoids the leak completely:

import subprocess
subprocess.run(["docker", "ps"])

Note:
To test this workaround inside the container, you must install the Docker CLI first:
apt update && apt install -y docker.io

Then you can validate with:
for i in $(seq 1 100); do python3 -c 'import subprocess; subprocess.run(["docker", "ps"])'; done

  • Can you confirm this as a bug in the SDK or socket/session cleanup under rootless Docker?
  • Could this be an issue with requests-unixsocket or how SDK wraps it?
  • Any known workaround or future fix?

Update: Tried Upgrading RootlessKit (v2.3.5)
We also upgraded RootlessKit to version 2.3.5 using the official release:
https://github.com/rootless-containers/rootlesskit/releases/download/v2.3.5/rootlesskit-x86_64.tar.gz

Confirmed it's in use via:
systemctl --user status docker

Output:

Loaded: loaded (/home/cc/.config/systemd/user/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2025-05-23 14:08:13 UTC; 21s ago
Docs: https://docs.docker.com/go/rootless/
Main PID: 37479 (rootlesskit)
CGroup: /user.slice/user-1001.slice/[email protected]/docker.service
        ├─37479 rootlesskit --net=vpnkit ...
        ├─37487 /proc/self/exe ...
        ├─37500 vpnkit --ethernet ...
        ├─37513 dockerd
        └─37543 containerd ...

Also verified version directly:
/bb/cc/docker_bin/rootlesskit --version

-> rootlesskit version 2.3.5

Despite the upgrade and confirmed restart of the rootless Docker daemon, the FD leak still persists when calling docker.from_env() repeatedly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions