Skip to content

[docker-in-docker] docker-in-docker fails on Ubuntu 24.04 containers on RHEL/AlmaLinux hosts: codename-based iptables fallback in v2.17.0 is too narrow #1659

@jmkle

Description

@jmkle

The fix introduced in PR #1637 (v2.17.0) for iptables-legacy failures on Ubuntu 26.04 uses a hardcoded VERSION_CODENAME check to decide whether to use iptables-nft vs iptables-legacy. This only handles Ubuntu 26.04 (resolute), but the same failure occurs on any Ubuntu/Debian container image running on a host kernel where the ip_tables module is not loaded, for example, AlmaLinux 9 or Fedora 41+ hosts.

Steps to Reproduce

  • Host OS: AlmaLinux 9 (or Fedora 41+): kernel does not load ip_tables by default
  • Devcontainer base image: mcr.microsoft.com/devcontainers/base:ubuntu-24.04 (codename: noble)
  • Feature: ghcr.io/devcontainers/features/docker-in-docker:2 (v2.17.0 / v3.x)

Starting the devcontainer results in:

failed to start daemon: Error initializing network controller: error obtaining controller instance:
failed to register "bridge" driver: failed to create NAT chain DOCKER: iptables failed:
iptables --wait -t nat -N DOCKER: iptables v1.8.10 (legacy): can't initialize iptables table `nat':
Table does not exist (do you need to insmod?)

Confirming manually inside the container:

$ iptables-legacy -nL
iptables v1.8.10 (legacy): can't initialize iptables table `filter': Table does not exist (do you need to insmod?)
# exits with code 3

$ type iptables-legacy
iptables-legacy is hashed (/usr/sbin/iptables-legacy)
# exits with code 0  <- binary exists, but kernel module is absent

Root Cause

In PR #1637, the initial fix correctly used a runtime -nL probe to verify whether iptables-legacy actually works before switching alternatives. However, this probe was removed because install.sh runs at image build time, when kernel modules are not accessible, so the probe would always fail during build.

The replacement logic uses a hardcoded codename allowlist:

case "${VERSION_CODENAME}" in
    resolute) use_nft=true ;;
esac

This only catches Ubuntu 26.04 (resolute). On Ubuntu 24.04 (noble) and any other non-resolute image the script falls through to:

elif type iptables-legacy > /dev/null 2>&1; then
    update-alternatives --set iptables /usr/sbin/iptables-legacy

Since type iptables-legacy succeeds (the binary exists), iptables-legacy is set as the default, even though the host kernel does not have ip_tables loaded. The failure only manifests at container runtime when dockerd tries to create the NAT chain.

This is the same underlying problem described in issue #1235 (Fedora/RHEL hosts), which also remains unresolved by the v2.17.0 fix.

Proposed Fix

The iptables alternatives selection logic should be moved from install.sh (build-time) to docker-init.sh (the runtime entrypoint script). At runtime, the -nL probe works correctly and can detect the actual kernel capability:

# In docker-init.sh, before starting dockerd:
if type iptables-legacy > /dev/null 2>&1 && iptables-legacy -nL > /dev/null 2>&1; then
    update-alternatives --set iptables /usr/sbin/iptables-legacy
    update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
elif type iptables-nft > /dev/null 2>&1; then
    update-alternatives --set iptables /usr/sbin/iptables-nft
    update-alternatives --set ip6tables /usr/sbin/ip6tables-nft
fi

This approach is host-kernel-agnostic and does not require maintaining a hardcoded list of codenames.

Environment

Host OS AlmaLinux 9
Container OS Ubuntu 24.04.3 LTS (noble)
Feature version ghcr.io/devcontainers/features/docker-in-docker:2 (v2.17.0 / v3.x)
Docker version 29.4.3-1
iptables version v1.8.10 (legacy)

Related Issues / PRs

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions