docker / docker/docker-py

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

Open
#3,338 1 comment 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
7.2k
Forks
1.7k
Avg merge
13d 8h
Merged PRs (30d)
2

Description

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/user@1001.service/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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No source file or test is named. Start by running the supplied rootless Docker reproduction with repeated docker.from_env() calls, then compare .close(), the Docker CLI subprocess workaround, and the tested docker, requests, and urllib3 versions. Done means identifying whether the SDK or socket/session cleanup causes the leak and documenting a verified fix or workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, python
Domain
backend, infrastructure
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.