Skip to content

Instantly share code, notes, and snippets.

@jfellus
Last active September 21, 2023 07:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jfellus/cfee9efc1e8e1baf9d15314f16a46eca to your computer and use it in GitHub Desktop.
Save jfellus/cfee9efc1e8e1baf9d15314f16a46eca to your computer and use it in GitHub Desktop.
Docker-compose (v2,v3) | Network interfaces order is tied to docker network names lexical order despite priority

Docker-compose network priority won't work, would it be v2 or v3

Deterministic docker-network to container interface is a must in multi-network setups Docker-compose has a priority mechanism to let the containers connect in order to the given networks

However, docker itself doesn't seem to take that into account

Instead, ethX order in the containers is determined by the lexical order of network names

How to reproduce

  • Run show_interfaces.sh
  • Observe how network one gets mapped to eth0 and two takes eth1 for every container despite various priority settings, simply because 'o' is before 't', and similarly for networks un and deux that respectively get mapped to eth1 and eth0 because 'u' if after 'd
  • Now, modify the docker-compose.yml at line 55 by renaming network un to _un, thus reversing the lexical order, without changing anything to priorities:
    un:
        name: _un # un -> _un
  • Run show_interfaces.sh again
  • Observe how networks un and deux got reversed just because of their names

More background

https://github.com/docker/compose/commit/f50e1a8c2d67e7aea7561c3122124eed019dd9d4 https://docs.docker.com/compose/compose-file/compose-file-v2/ libnetwork seems to be ok on that : moby/libnetwork#2093 related to https://gist.github.com/gentunian/1363b57255af3bd04a8000175948be4f

By 2016, the "official" behavior was to follow lexical order : moby/libnetwork#1141 (comment). But this has been removed from the docs : https://docs.docker.com/network/ (this page used to contain

When a container is connected to multiple networks, its external connectivity is provided via the first non-internal network, in lexical order.

at that time).

https://forums.docker.com/t/multiple-networks-in-a-docker-compose-file-precedence/39071/2

moby/moby#20179

version: "2.0"
services:
a:
image: alpine
networks:
one:
priority: 10
two:
priority: 1
command: ip r
b:
image: alpine
networks:
two:
priority: 10
one:
priority: 1
command: ip r
c:
image: alpine
networks:
- one
- two
command: ip r
x:
image: alpine
networks:
un:
priority: 10
deux:
priority: 1
command: ip r
y:
image: alpine
networks:
un:
priority: 10
deux:
priority: 1
command: ip r
z:
image: alpine
networks:
- un
- deux
command: ip r
networks:
one:
name: one
two:
name: two
un:
name: un
deux:
name: deux
#!/bin/bash
docker-compose up --no-color 2>/dev/null | grep scope | sort -k3 > out1.tmp
docker network inspect $(docker network ls -q) --format '{{.Name}} {{range .IPAM.Config}}{{.Subnet}}{{end}}' | sort -k2 > out2.tmp
join out1.tmp out2.tmp -1 3 -2 2 | awk '{print $2,$5,$10,$9}' | sort -k1
docker-compose rm -f >/dev/null 2>&1
rm *.tmp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment