Safely Prune Unused Docker Networks

Run docker network prune against the wrong context and you can wipe out networks a live deployment still expects, with no undo flag to bail you out.

You will finish with a controlled way to remove Docker networks that no container references, checking the candidates first and steering clear of the networks Docker treats as system networks. Allow about ten minutes. You need a working Docker daemon and permission to query and change its networks. The examples were checked against Docker CLI 29.8.1 from docker-ce-cli version 5:29.8.1-1~ubuntu.24.04~noble.

Warning: pruning is destructive. A removed network cannot be restored by an undo flag, and any external configuration that names it may need to be recreated. Do not run the removal step during a deployment, or while you are still deciding whether an old Compose project will return. Make a list first, then apply a narrow filter or confirm the full removal set.

1. Check the daemon and command syntax

Start with read-only checks. These ordinary commands usually need no elevated privileges when your account can already reach Docker:

$ docker version --format '{{.Client.Version}}'
29.8.1
$ docker network prune --help
Usage:  docker network prune [OPTIONS]

Remove all unused networks

Options:
      --filter filter   Provide filter values (e.g. "until=<timestamp>")
  -f, --force           Do not prompt for confirmation

The command acts on the daemon your current context and environment select, not necessarily the host your shell is running on. Check that context before you inspect a production daemon:

$ docker context show
default
$ docker info --format '{{.Name}}'

If Docker reports a permission error, fix access to the intended socket through your normal administrator process. Adding your account to a Docker access group grants broad control over the host, so never treat that as a harmless shortcut.

2. Inventory networks and connected containers

List the networks before removing anything. This gives you names and drivers to check against your deployment notes:

$ docker network ls --format 'table {{.ID}}	{{.Name}}	{{.Driver}}	{{.Scope}}'
NETWORK ID     NAME              DRIVER    SCOPE
...            bridge            bridge    local
...            project_default   bridge    local
...            old-test-net      bridge    local

For any candidate whose purpose is unclear, inspect it before pruning:

$ docker network inspect old-test-net

Checkpoint: write down the Docker context and the candidate names you expect to disappear. If the list includes a network a live service uses, stop and investigate that service instead of forcing removal.

3. Preview a time-based cleanup

The safest repeatable pattern combines the unused-network test with an age filter. This example limits pruning to unused networks created more than 24 hours ago:

$ docker network prune --filter 'until=24h'

Without --force, Docker prints a warning and asks for confirmation. Read the candidate names in the prompt, and answer y only when they match your inventory. The duration is evaluated against the daemon machine's clock, not necessarily your workstation's.

For automation, use an explicit filter with --force, but only after the policy has been tested interactively:

$ docker network prune --force --filter 'until=24h'
Deleted Networks:
old-test-net

The names shown are examples. Your run may delete nothing, or several networks. A successful command does not mean every old network was removed: ones with attached containers, and system networks, stay outside this operation.

4. Filter by labels when age is not enough

Labels let you target networks created for a particular lifecycle. This removes only unused networks carrying the temporary=true label and older than 24 hours:

$ docker network prune --filter 'label=temporary=true' --filter 'until=24h'

Different filter keys combine with AND logic, so a network must satisfy both conditions. Repeating the same key uses OR logic instead, so two label filters match either one:

$ docker network prune --filter 'label=temporary=true' --filter 'label=owner=ci' --filter 'until=24h'

Docker also supports negative label filters such as label!=keep. Treat these carefully: a missing label can make a network match. Quote the filter value so shell characters stay part of the Docker argument.

Do not assume a label exists just because it appears in a Compose file or deployment script. Verify it with docker network inspect NETWORK_NAME first. If the label policy is not documented, fall back to the age-only command with an interactive confirmation.

5. Verify the result and recover deliberately

After pruning, list networks again and inspect any name that should have survived:

$ docker network ls
$ docker network inspect project_default

The built-in bridge, host and none networks are system networks and are never pruned. Other networks stay when a container still references them. If an application fails because it expected a network you deliberately removed, recreate the network from its original provisioning or Compose configuration, then reconnect or recreate the affected containers according to that service's runbook. Do not guess the subnet, driver options or labels from memory.

Recovery: there is no general rollback for docker network prune. A successful removal deletes the network object and its Docker-managed state for good. The practical recovery is to restore the declarative configuration and redeploy the workload, so keep that configuration and any required network parameters available before a scheduled cleanup.

Done means