# Docker Container Network Interface Ordering


Lately I've found myself routinely attaching Docker-based containers to
multiple networks.  This has led to a couple... interesting surprises.

<!--more-->

It doesn't seem to be well documented (AFAIK), so here's what I've learned.
This isn't a big serious how-to post, just something that irked me. :smile:

## Tooling (a little background)

{{< admonition note "Observed behavior" false >}}

As this is observed behavior rather than documented (AFAICT, at any rate), it
may change without warning.

Oh well.

{{< /admonition >}}

For the purposes of this article, let's say we're using the following tools:

* [docker](https://github.com/docker)
* [docker-compose](https://github.com/docker/compose)

## Network name determines ordering

{{< admonition tip "What's the actual network name?" true >}}

When using Compose, there are really two network "names" for each network.

1. The name specified in the Compose configuration; and
2. The name Compose uses when creating the Docker network.

In a compose configuration, we always use #1 to refer to a network; however
behind the scenes this will be different from the name of the network as known
to Docker.

{{< /admonition >}}

Networks are attached in alphabetical order.  Internal networks are attached
last, though still in alphabetical order.

Networks appear to be attached in alphabetical order, further segregated by
the internal status.  Not-internal networks are attached to the container
before internal networks.

Let's say we have a container with three networks attached:

```yaml
version: "3.9"

services:
  container1:
  image: docker.io/containous/whoami
    networks:
      backend: {}
      frontend: {}
      apples: {}
      oranges: {}

networks:
  backend: {}
  frontend: {}
  apples:
    internal: true
  oranges:
    name: lemons
```

Let's say this has a project name of `services`.  When `container1` is
launched, it will see a number of interfaces:

| Interface | Network (Compose) | Network (Docker)    |
|-----------|-------------------|---------------------|
| `eth0`    | `oranges`         | `lemons`            |
| `eth1`    | `backend`         | `services_backend`  |
| `eth2`    | `frontend`        | `services_frontend` |
| `eth3`    | `apples`          | `services_apples`   |

Why?  `apples` is internal, so it ends up at the end of the list.  `oranges`
has an actual name of `lemons`, so it ends up before the other networks with
a `services_` prefix.

## Default route is always through `eth0`

If you want a specific network to be the default route, you're going to need
to make sure it's first -- alphabetically.

### Routing and macvlan interfaces

This is more of a corner case.  If you're attaching containers directly to a
vlan/network using, say, `macvlan`, and that network ends up being your
default route (`app_vlan`, anyone?), then all traffic for networks you're not
directly connected to will be routed over this vlan.

This may or may not matter, but if you have the (reasonable) expectation that
non-local traffic will route through and be masqueraded by the host, this can
be surprising.


---

> Author: Chris Weyl  
> URL: https://weyl.io/2022/01/docker-container-network-interface-ordering/  

