Skip to content

Docker Network Lifecycle Management


We’ve now used Docker networks enough to stop treating them as something that just appears when a container starts.

A network is a Docker resource with its own lifecycle.

You can create one, inspect it, attach containers to it, detach containers from it, and eventually remove it.

The useful mental model is:

Network
   |
   +── exists
   |
   +── containers connected
   |
   +── no containers connected
   |
   └── removed

Let’s walk through that lifecycle.

List Existing Networks

Start by seeing what networks Docker already knows about:

docker network ls

On a typical Docker installation you’ll see built-in networks such as:

NETWORK ID     NAME      DRIVER    SCOPE
...            bridge    bridge    local
...            host      host      local
...            none      null      local

These are Docker’s built-in networks.

You normally don’t remove these as part of ordinary cleanup.

The networks we create ourselves have their own lifecycle.

Create a Network

Create a user-defined bridge network:

docker network create app-net

Docker returns the network ID.

Now list the networks again:

docker network ls

You should see:

app-net

The network now exists independently of any container.

That’s important:

docker network create app-net
            |
            v
        app-net
            |
            +── no containers yet

A network doesn’t need a container to exist.

Inspect the Network

To see what Docker knows about the network:

docker network inspect app-net

You’ll find information such as:

  • network name
  • driver
  • subnet
  • gateway
  • connected containers

When the network is newly created, the container list will be empty.

Conceptually:

app-net
   |
   +── Driver: bridge
   |
   +── Subnet: ...
   |
   +── Gateway: ...
   |
   └── Containers: none

This is one of the most useful commands when something about Docker networking isn’t behaving as expected.

Connect a Container

Now create a container and connect it to the network:

docker container run -d \
  --name app \
  --network app-net \
  alpine:latest \
  sleep 300

The network now has a container attached to it:

app-net
   |
   └── app

Inspect it again:

docker network inspect app-net

You should now see app under the connected containers.

The lifecycle has moved from:

Network exists
      ↓
No containers

to:

Network exists
      ↓
Container connected

A Network Can Have Multiple Containers

Create another container:

docker container run -d \
  --name database \
  --network app-net \
  alpine:latest \
  sleep 300

Now:

          app-net
          /     \
         /       \
       app     database

Both containers are members of the same user-defined bridge network.

They can use the network features you’ve already learned, including Docker’s built-in name resolution.

For example, from app:

docker container exec app ping -c 1 database

The exact output isn’t important here.

The important point is that database is now a container connected to the same user-defined network.

Disconnect a Container

A network doesn’t permanently belong to a container.

You can explicitly disconnect a container:

docker network disconnect app-net database

Now:

app-net
   |
   └── app

database is no longer connected.

You can confirm this with:

docker network inspect app-net

The container should no longer appear in the network’s connected-container list.

The lifecycle now looks like:

app-net
   |
   +── app
   |
   └── database disconnected

Connect It Again

If you change your mind:

docker network connect app-net database

Now database is back:

          app-net
          /     \
         /       \
       app     database

This is useful when a container already exists and you want to change which networks it belongs to.

Notice the difference between:

docker container run --network app-net ...

and:

docker network connect app-net <container>

The first connects the container to the network as part of container creation.

The second connects an existing container to the network.

A Container Can Be on Multiple Networks

This is an important property of Docker networking.

A container isn’t necessarily limited to one network.

For example:

docker network create frontend
docker network create backend

Then create a container on frontend:

docker container run -d \
  --name app \
  --network frontend \
  alpine:latest \
  sleep 300

Connect the same container to backend:

docker network connect backend app

Now:

    flowchart LR
    A["app"]
    B["backend"]
    F["frontend"]
    A --> B
    A --> F
  

The same container belongs to both networks.

This can be useful when a container needs to communicate with different groups of containers.

You don’t need to memorize complex architecture here. Just remember:

A container can be connected to more than one Docker network.

What Happens When a Container Is Removed?

This is where the network lifecycle differs from the container lifecycle.

Remove a container:

docker container rm -f database

The container disappears.

The network remains:

app-net
   |
   └── app

If database was the only container, the network would simply become empty:

app-net
   |
   └── no containers

Docker does not automatically remove the user-defined network just because its containers disappeared.

That’s important because you may want to reuse the same network later.

An Empty Network Is Still a Network

Suppose you remove every container from app-net.

You can still run:

docker network inspect app-net

The network exists.

You can then create a completely new container and attach it to the same network:

docker container run -d \
  --name new-app \
  --network app-net \
  alpine:latest \
  sleep 300

So:

Network
   |
   +── empty
   |
   └── reusable

This is another example of Docker resources having independent lifecycles.

Remove a Network

When you no longer need the network:

docker network rm app-net

Docker removes the network.

But there is an important restriction.

A network that still has containers connected to it cannot simply be removed.

For example:

app-net
   |
   +── app
   +── database

Trying:

docker network rm app-net

will fail because the network is still in use.

Docker makes you deal with the connected containers first.

You can either:

docker network disconnect app-net app
docker network disconnect app-net database

and then remove the network:

docker network rm app-net

or remove the containers that are using the network.

The exact cleanup depends on whether those containers are still needed.

Network Pruning

Over time, you might create networks for experiments and forget about them.

Docker provides:

docker network prune

This removes unused user-defined networks.

Docker asks for confirmation first.

You can skip the confirmation with:

docker network prune --force

The important word is:

unused

A network with containers still connected to it is not considered unused in the normal sense relevant to pruning.

Built-in networks such as bridge, host, and none are not simply wiped out by this cleanup.

Warning

docker network prune is a cleanup command. Before using it on a real Docker host, make sure unused networks are genuinely disposable.

Useful Filters

You can filter network listings:

docker network ls --filter name=app

This is handy when the host has many networks.

You can also filter by driver:

docker network ls --filter driver=bridge

The exact filters you use will depend on what you’re trying to find, but the important pattern is:

docker network ls --filter ...

Useful Network Commands

The core commands are small enough to remember:

CommandPurpose
docker network lsList networks
docker network create NAMECreate a network
docker network inspect NAMEInspect a network
docker network connect NETWORK CONTAINERConnect an existing container
docker network disconnect NETWORK CONTAINERDisconnect a container
docker network rm NAMERemove a network
docker network pruneRemove unused networks

And when creating a container:

docker container run \
  --network NETWORK \
  IMAGE

connects it to the specified network at creation time.

The Network Lifecycle

Now put the whole lifecycle together:

    stateDiagram-v2
    [*] --> Created: docker network create
    Created --> Connected: container joins
    Connected --> Connected: another container joins
    Connected --> Empty: last container disconnects
    Connected --> Empty: last container removed
    Empty --> Connected: container joins again
    Empty --> Removed: docker network rm
    Empty --> Removed: docker network prune
    Removed --> [*]
  

The important states are:

Created
   ↓
Connected
   ↓
Empty
   ↓
Removed

And the lifecycle is independent from any one container.

A container can come and go while the network survives.

Network vs Container Lifecycle

This distinction is worth seeing side by side.

Container

create
  ↓
running
  ↓
stopped
  ↓
removed

Network

create
  ↓
containers connected
  ↓
empty
  ↓
removed

Removing the container doesn’t automatically destroy the network.

Removing the network doesn’t mean “remove all containers” either — Docker will normally refuse to remove a network while containers are still connected.

They are separate resources.

A Practical Cleanup Sequence

Suppose you created:

app-net
   |
   +── app
   +── database

and the experiment is finished.

One clean approach is:

docker container rm -f app database
docker network rm app-net

After that:

docker network ls

should no longer show app-net.

For a forgotten collection of unused networks, you can instead use:

docker network prune

The difference is:

network rm
   ↓
"I know exactly which network I want to delete."

network prune
   ↓
"Clean up unused networks."

What You Should Remember

You don’t need to memorize every flag.

Remember the lifecycle:

CREATE
  ↓
CONNECT
  ↓
USE
  ↓
DISCONNECT
  ↓
REMOVE

And the core commands:

docker network create
docker network ls
docker network inspect
docker network connect
docker network disconnect
docker network rm
docker network prune

The most important conceptual point is:

A Docker network is an independent resource. Containers can join and leave it without determining whether the network itself exists.

That same lifecycle thinking will make Docker volumes much easier to understand.

Last updated on