You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
nerdctl requires CNI to be installed when running containers with network_mode host #4461
Running containers with network_mode: host, nerdctl still tries to create a default network even when no containers require one.
Steps to reproduce the issue
Do not have a CNI installed on your host
Try to start a container with network_mode: host (nerdctl run --rm -it --network host alpine sh or nerdctl compose up -d with a compose file with network_mode: host)
FATA[0000] failed to create default network: needs CNI plugin "bridge" to be installed in CNI_PATH ("/opt/cni/bin"), see https://github.com/containernetworking/plugins/releases: exec: "/opt/cni/bin/bridge": stat /opt/cni/bin/bridge: no such file or directory
Describe the results you received and expected
I expected nerdctl to not try to create a default network when none of my containers need one.
Docker is able to start these containers without creating a docker bridge/network
What version of nerdctl are you using?
v2.1.3 (latest)
Are you using a variant of nerdctl? (e.g., Rancher Desktop)
It's not just host -- it looks like the bridge network is always getting created, even with none. This appears specific to v2.2.0, as v2.1.6 behaves correctly. In both cases, I'm using containerd v2.1.5.
My specifics:
I'm running a Kubernetes node with Cilium which also (don't ask why) needs to run nerdctl. What happens is:
nerdctl run --net none hello-world
nerdctl creates the bridge network anyway
cilium deletes it
containerd calls runc
runc can't find the "bridge" network:
nerdctl run hello-world --net none
FATA[0000] failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running createRuntime hook #0: exit status 1, stdout: , stderr: time="2025-12-07T06:51:51Z" level=fatal msg="no such network: \"bridge\""
Reproduced on current main (2.3.5-0.20260805080927-fcaa66c54420, containerd 2.3.3, a host with
no CNI plugins installed at all). The report splits into two halves that behave differently today:
The plain run half no longer reproduces. With an empty CNI_PATH, both of these succeed:
nerdctl run --rm --net host alpine echo OK -> OK
nerdctl run --rm --net none alpine echo OK -> OK
NewNetworkingOptionsManager dispatches host and none to their own managers, neither of which
touches CNI, and the OCI hook already returns early for nettype.Host / nettype.None
(pkg/ocihook/ocihook.go:178).
The compose half still fails. With the same empty CNI_PATH:
services:
probe:
image: alpinenetwork_mode: hostcommand: echo OK
FATA[0000] failed to create default network: needs CNI plugin "bridge" to be installed in
CNI_PATH ("/opt/cni/bin") ...
Cause is compose.New (pkg/cmd/compose/compose.go:55), which passes netutil.WithDefaultNetwork(...) to NewCNIEnv. That creates nerdctl's default bridge before a
single service has been parsed, so it happens no matter what network_mode the services declare.
The CNIEnv built there is only used for NetworkExists, which up_network.go and down.go call
exclusively with project-scoped names such as myproject_default, and external networks return
before reaching it. Nothing in that path needs the default bridge to exist.
@mwinters0 on the v2.1.6 vs v2.2.0 point: I could not confirm a regression window there. Every WithDefaultNetwork call site is identical across v2.1.6, v2.2.0 and main, and the diff between
those two tags in the networking path is checkpoint and healthcheck work that does not touch it.
One thing worth checking on your side: in the failing command you posted, --net none comes after
the image name, where it is treated as an argument to the container rather than as a flag. If it
still reproduces with the flag before the image, that is likely a separate bug and worth its own
issue.
PR shortly, with the fix scoped to the compose path plus a regression test.
Activity
mwinters0 commentedon Dec 7, 2025
It's not just
host-- it looks like the bridge network is always getting created, even withnone. This appears specific to v2.2.0, as v2.1.6 behaves correctly. In both cases, I'm using containerd v2.1.5.My specifics:
I'm running a Kubernetes node with Cilium which also (don't ask why) needs to run nerdctl. What happens is:
nerdctl run --net none hello-worldkamlane commentedon Dec 29, 2025
I'm seeing this same behavior with containerd 1.7.28 and nerdctl version 2.2.1 however I have cilium installed.
feat(registry): pin nerdctl 1.7.7 and add HTTPS variant
ravi-arnan commentedon Aug 8, 2026
I would like to work on this.
Reproduced on current main (
2.3.5-0.20260805080927-fcaa66c54420, containerd 2.3.3, a host withno CNI plugins installed at all). The report splits into two halves that behave differently today:
The plain
runhalf no longer reproduces. With an emptyCNI_PATH, both of these succeed:NewNetworkingOptionsManagerdispatches host and none to their own managers, neither of whichtouches CNI, and the OCI hook already returns early for
nettype.Host/nettype.None(
pkg/ocihook/ocihook.go:178).The compose half still fails. With the same empty
CNI_PATH:Cause is
compose.New(pkg/cmd/compose/compose.go:55), which passesnetutil.WithDefaultNetwork(...)toNewCNIEnv. That creates nerdctl's default bridge before asingle service has been parsed, so it happens no matter what
network_modethe services declare.The
CNIEnvbuilt there is only used forNetworkExists, whichup_network.goanddown.gocallexclusively with project-scoped names such as
myproject_default, and external networks returnbefore reaching it. Nothing in that path needs the default bridge to exist.
@mwinters0 on the v2.1.6 vs v2.2.0 point: I could not confirm a regression window there. Every
WithDefaultNetworkcall site is identical across v2.1.6, v2.2.0 and main, and the diff betweenthose two tags in the networking path is checkpoint and healthcheck work that does not touch it.
One thing worth checking on your side: in the failing command you posted,
--net nonecomes afterthe image name, where it is treated as an argument to the container rather than as a flag. If it
still reproduces with the flag before the image, that is likely a separate bug and worth its own
issue.
PR shortly, with the fix scoped to the compose path plus a regression test.
fix: do not require CNI plugins for compose projects that avoid CNI