Lesstep
GitHub Actions · Ubuntu 26.04 · Checked November 4, 2026

"can't initialize iptables table `nat'": Docker-in-Docker on Ubuntu 26.04

ubuntu-latest is moving from Ubuntu 24.04 to 26.04 between October 19 and November 19, 2026 (what else changes). The 26.04 image runs kernel 7.0, which builds the legacy iptables tables as modules and does not load them: ip_tables, iptable_filter, iptable_nat, ip6_tables and ip6table_filter. On 24.04 they were loaded. Docker on the runner itself uses nftables, so it is fine, but a container that calls iptables-legacy cannot load them, and a dockerd inside it stops at its first NAT rule.

What it looks like

With the dev container docker-in-docker feature, the job log shows only the retry line, four times:

(*) Failed to start docker, retrying...
(*) Failed to start docker, retrying...
(*) Failed to start docker, retrying...
(*) Failed to start docker, retrying...
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

The reason is in /tmp/dockerd.log inside the container, which the feature's docker-init.sh writes and nothing prints:

failed to start daemon: Error initializing network controller: ... failed to create NAT chain DOCKER:
iptables v1.8.11 (legacy): can't initialize iptables table `nat': Table does not exist (do you need to insmod?)

Your own iptables-legacy calls in a container fail the same way, with filter instead of nat.

Why the feature picks legacy

Versions 2 and 3 of the feature choose the iptables alternative when the image is built, from the image's own distribution: iptables-nft only when the image itself is Ubuntu 26.04, and iptables-legacy for everything else, including Debian bookworm and trixie and Ubuntu 22.04 and 24.04. The :2 tag stopped at 2.17.0 in May 2026 and :3 at 3.1.0, so neither gets a later fix. Version 4.0.0 (June 2026) moved the choice to container start, on by default (iptablesSwitchAtRuntime), and uses legacy only when the host has ip_tables loaded (devcontainers/features #1666).

Where the reports came from

Fix: move the feature to version 4

"features": {
  "ghcr.io/devcontainers/features/docker-in-docker:4": {}
}

If the repository has devcontainer-lock.json, update its docker-in-docker entry too: it holds the exact version and digest, and the failing project's lock still said 2.17.0. A prebuilt dev container image keeps the old choice until you rebuild it. If the container's entrypoint runs as a non-root user, use 4.1.3 or later (#1747). Version 2 to 4 is two major versions, so read the feature's options before switching.

Or load the modules on the runner

- run: sudo modprobe -a ip_tables iptable_filter iptable_nat ip6_tables ip6table_filter

Run this before the step that starts the container. It works for any container that uses iptables-legacy, not only the feature, and the project in aios #2567 does this in CI. On a self-hosted 26.04 host, load them at boot instead, with a file in /etc/modules-load.d/ that lists the five modules.

Pinning the job to runs-on: ubuntu-24.04 also works, until GitHub retires that image.

Telling it apart

Other 26.04 failures

See failed jobs from IntelliJ IDEA

Pipeline Inbox for GitHub Actions Workflows, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the runs of all your repositories in an IDE tool window, with their jobs and steps, and your current branch's runs are in the status bar. Reading is free; re-running failed jobs, cancelling, running workflows and reviewing deployments are Pro (US$1.50 a month, with a 30-day trial).

Get it on JetBrains Marketplace

GitHub and GitHub Actions are trademarks of GitHub, Inc.; Ubuntu is a trademark of Canonical Ltd.; Docker is a trademark of Docker, Inc.; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with, sponsored or endorsed by GitHub, Inc., Canonical, Docker, Inc. or JetBrains.

More: "The ubuntu-latest label will migrate to Ubuntu 26" · Postgres never starts in Docker on Ubuntu 26.04 · GitHub Actions plugins for IntelliJ IDEA compared · 日本語