Compose: docker-compose 1.27.0 appears to have broken using external overlay networks

Created on 8 Sep 2020  路  8Comments  路  Source: docker/compose

Description of the issue

networks:
  mynetworkname:
    external: true
    driver: overlay

produces

ERROR: Network mynetworkname declared as external but specifies additional attributes (driver).

Context information (for bug reports)

Output of docker-compose version

docker-compose version 1.27.0, build unknown
docker-py version: 4.3.1
CPython version: 3.6.9
OpenSSL version: OpenSSL 1.1.1  11 Sep 2018

Output of docker version

docker-compose version 1.27.0, build unknown
docker-py version: 4.3.1
CPython version: 3.6.9
OpenSSL version: OpenSSL 1.1.1  11 Sep 2018
root@proxy-staging-8:/opt/demo-compose-bug# docker version
Client: Docker Engine - Community
 Version:           19.03.12
 API version:       1.40
 Go version:        go1.13.10
 Git commit:        48a66213fe
 Built:             Mon Jun 22 15:45:36 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.12
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.10
  Git commit:       48a66213fe
  Built:            Mon Jun 22 15:44:07 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

Output of docker-compose config
(Make sure to add the relevant -f and other flags)

ERROR: Network mynetworkname declared as external but specifies additional attributes (driver).

Steps to reproduce the issue

  1. Have a swarm overlay network, here named "mynetworkname"
  2. pip3 install docker==4.3.1 docker-compose==1.27.0
    2.
mkdir demo && cd demo
cat >> docker-compose.yml << EOF
version: "3.7"
services:
  somecontainer:
    image: alpine
    command: sleep 9999999
    networks:
    - mynetworkname
networks:
  mynetworkname:
    external: true
    driver: overlay
EOF
docker-compose up -d

Observed result

ERROR: Network mynetworkname declared as external but specifies additional attributes (driver).

Expected result

WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

Creating demo_somecontainer_1 ... done

(Reverting with pip3 install docker==4.3.1 docker-compose==1.26.2 fixes and lets me get this again)

Stacktrace / full error message

Sorry, I don't understand how that's different from "Observed result".

Additional information

Ubuntu 18.04.5 LTS, installed with pip (see steps to reproduce above).

kinbug

Most helpful comment

Oh, that's actually quite nice. So then what needs to happen is that for any existing network I'm attaching things to, I should only ever specify the name and the property external: true, because everything else is already defined, correct?

All 8 comments

To reiterate explicitly rather than in the middle of the reproduction steps, this works with docker-compose==1.26.2 and not docker-compose==1.27.0

Hi @briancolecoinmetrics!

In 1.27.0 we have a strict check of the properties we can set in the compose file. In old versions of docker-compose, you could add in many cases random properties in the compose file that would have been silently ignored and that behaviour is very confusing as you never know what has been applied or ignored. With the stricter validation, we error out if a property that is unknown/unsupported is set in the compose file.

In your case, you try to use an external network that has already been created. Passing a driver property in such a case is no good because the network has already been created. It works with 1.26.x versions because it is silently ignored.

We can set the driver for networks we want to be created as the request to the docker engine looks as below:

Calling POST /v1.38/networks/create          
 form data: {"Attachable":true,"CheckDuplicate":true,"Driver":"overlay","Labels":{"com.docker.compose.network":"mynetworkname","com.docker.compose.project":"nginx","com.docker.compose.version":"1.26.2"},"Name":"nginx_mynetworkname"}

When using an external network, we skip the network creation and only pass the name of the network in the container's NetworkConfig to have it attached to the already existing network:

Calling POST /v1.38/containers/create?name=nginx_somecontainer_1 
form data: {
....
"NetworkDisabled":false,"NetworkingConfig":{"EndpointsConfig":{"nginx_mynetworkname":{"Aliases":["somecontainer"],"IPAMConfig":{}}}},
....} 

Oh, that's actually quite nice. So then what needs to happen is that for any existing network I'm attaching things to, I should only ever specify the name and the property external: true, because everything else is already defined, correct?

Ah, and now I know why we were doing that. So by way of background, we're using docker swarm exclusively for its overlay network feature (we just make our networks all attachable), while actually running stuff using docker-compose (run by ansible). It turns out that if I remove the driver specification, it can't find the network; I get

ERROR: Network mynetworkname declared as external, but could not be found. Please create the network manually using `docker network create mynetworkname` and try again.

This was apparently something that we rolled out after chasing what appears to be problems getting docker to propagate networks to servers, and it appears to have worked reasonably well.

@briancolecoinmetrics Please keep in mind that if you create a network with docker-compose, the network name is prefixed with the project name.

In your example (once you remove the external, assume we want to create the network), the actual network name will end up being demo_mynetworkname. So when you try in another compose file to set it as external, you have to set this name otherwise it will look for mynetworkname and that network doesn't exist.

mkdir demo && cd demo
cat >> docker-compose.yml << EOF
version: "3.7"
....
networks:
  mynetworkname:
    driver: overlay
EOF
docker-compose up -d

Or as alternative, do a docker network ls to check that you have that network before running the compose file with the external property.

I'm not trying to create a network; I want to have docker-compose create a container that's attached to an existing swarm overlay network, originally created on a manager with docker network create -d overlay --attachable --opt encrypted mynetworkname.

Running docker network ls doesn't show the network, because it's not on the server until the container is run, but if I use docker-compose 1.26.2 and set driver: overlay then the network will get propagated to the server and it'll work.

@briancolecoinmetrics My bad, I wasn't aware of this limitation. Found the code concerning it:
https://github.com/docker/compose/blob/b111ef63224f0f08d999e197f9b63675ffe4ee76/compose/network.py#L47-L50

I'll prepare a PR to re-enable the driver property for external networks in 1.27.1

I've deployed 1.27.2 and can confirm that this is now fixed. Thanks!

Was this page helpful?
0 / 5 - 0 ratings