Skip to content

install: wait up to 60 seconds for dpkg locks - #582

Open
soulteary wants to merge 1 commit into
docker:masterfrom
soulteary:codex/feat/apt-lock-wait-upstream
Open

soulteary wants to merge 1 commit into
docker:masterfrom
soulteary:codex/feat/apt-lock-wait-upstream

Conversation

@soulteary

@soulteary soulteary commented Oct 5, 2026 •

Copy link
Copy Markdown

Temporary dpkg contention from another package installation currently makes the installer's APT package installations fail immediately. This change gives the prerequisite and Engine installation commands a fixed, bounded 60-second wait; contention that outlasts the timeout still fails.

- What I did

  • Added -o DPkg::Lock::Timeout=60 to the two executed APT installation commands in install.sh: prerequisites and Docker Engine packages.
  • Added the same option to the rootless installer's two printed dependency-installation instructions for uidmap and iptables.
  • Added an offline command-generation regression suite, real dpkg lock tests in disposable containers, a dedicated CI job, and reproducible instructions in README.

The production change is limited to those four installation command strings. Both command -v apt-get availability checks and both apt-get update commands remain unchanged. Package selection, -y, -qq, and the existing --allow-downgrades behavior are preserved.

- How I did it

The change uses APT's existing dpkg lock-acquisition timeout, without adding a retry loop. APT introduced this capability in 1.9.11; older APT versions do not provide this waiting behavior. The 60-second setting bounds waiting for the dpkg frontend and administration locks, rather than the duration of the complete package installation.

DPkg::Lock::Timeout does not cover the /var/lib/apt/lists/lock used by apt-get update. The update commands retain their existing behavior, and the live suite includes a negative check for this limitation. See the APT lists-lock report.

This revised implementation builds on the proposal by oreze in docker/docker-install#431, keeping APT runtime options out of executable-availability checks and update commands.

The upstream candidate is based on the master snapshot 2b32480025b223ebfddae9a3a8bef09027680f53. Candidate commit 47854e0b70801b61127fabf8e3e27e0ca8050353 records its cherry-pick provenance from implementation commit b3f6b21e17e44c4c64d692881bac706b35596ad2, and carries the DCO sign-off:

Signed-off-by: Su Yang <soulteary@users.noreply.github.com>

- How to verify it

Run the offline and static checks:

python3 scripts/test-apt-lock-wait.py
sh -n install.sh
sh -n rootless-install.sh
shellcheck -e SC1091,SC1117,SC2317,SC2329 install.sh rootless-install.sh
git diff --check

The offline suite executes captured installer control flow using Ubuntu and Debian fixtures. It checks unpinned installations, --version 27.5 and its --allow-downgrades flag, both prerequisite and Engine installation commands, repository-only mode, unchanged update commands, and rootless APT availability/dependency instructions. Package-manager, download, privilege, and service commands are guarded against accidental execution during these checks.

The before-change regression control used fork commit c57bd8230308fc38ec5d199db5c7b95eac35d9c7. The final regression suite rejects that control for the missing installation lock-timeout options; the revised implementation passes. This fork regression-control snapshot is separate from the upstream master candidate base identified above.

Run real lock tests only in an explicitly opted-in disposable container:

docker run --rm -v "$PWD:/v:ro" -w /v \
  -e DOCKER_INSTALL_LOCK_TEST_CONTAINER=1 ubuntu:24.04 sh -ec '
    apt-get -qq update
    DEBIAN_FRONTEND=noninteractive apt-get -o DPkg::Lock::Timeout=60 -y -qq install --no-install-recommends python3 >/dev/null
    python3 scripts/test-apt-lock-wait.py --live
  '

The final test script was completely exercised locally in these official containers:

  • ubuntu:24.04: APT 2.8.3, amd64; held-lock timeout measured 60.2 seconds.
  • debian:12-slim: APT 2.6.1, arm64; held-lock timeout measured 60.0 seconds.

Both final runs verified:

  • An APT installation command without the timeout fails immediately with exit 100 while another process holds the real frontend lock.
  • The generated prerequisite/Engine installation options wait successfully for frontend/administration locks released by the lock holder.
  • A frontend lock held throughout the wait causes exit 100 after the actual 60-second timeout, and the command-line setting overrides an APT configuration default of zero.
  • Lists-lock contention still makes apt-get update fail immediately, even when the dpkg timeout option is supplied.

The live suite uses Python fcntl record locks. It obtains the installed bash version with dpkg-query, pins that exact version, and disables downloads. It never deletes lock files. Python is installed only while preparing the disposable test containers; these checks do not install Docker, validate Docker package dependencies, or verify daemon/service startup.

Local shell syntax, ShellCheck, Python syntax, CI YAML structure, and git diff --check passed. The dedicated candidate CI matrix also passed in the fork candidate CI run for ubuntu:22.04, ubuntu:24.04, and debian:12-slim. Those fork-side results are prior candidate validation; they are not presented as results from this newly opened upstream PR's CI run.

- Description for the changelog

Wait up to 60 seconds for dpkg locks during APT package installation.

Signed-off-by: Su Yang <soulteary@users.noreply.github.com>
(cherry picked from commit b3f6b21)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant