Can't connect to other containers inside docker network

I have a few containerized projects I would like to talk to each other into a network called ‘dev_network’.

I would expect to be able to start up both containers and be able to ping them from inside the containers…

E.g. I should be able to ping foo from bar, but I cannot.

root@75cba11f489c:/# ping bar
ping: bar: Name or service not known

These projects live in separate folders, but I would like them to connect to the same network and be able to talk to each other.

Here’s a simple configuration that shows the problem

There’s a foo service and a bar service.

Here is the Dockerfile for the foo service:

FROM debian:stretch-slim

RUN set -x  && apt-get update && apt-get install -y apt-utils
RUN set -x  && apt-get install -y iputils-ping

ENTRYPOINT ["/bin/bash"]

The Dockerfile for the bar service is identical:

FROM debian:stretch-slim

RUN set -x  && apt-get update && apt-get install -y apt-utils
RUN set -x  && apt-get install -y iputils-ping

ENTRYPOINT ["/bin/bash"]

Here’s the docker-compose.yml for the foo service:

version: '3.5'
services:
  foo:
    image: foo
    build:
      context: .
      dockerfile: Dockerfile

networks:
  default:
    name: dev_network
    driver: bridge

And the only slightly different docker-compose.yml for the bar service:

version: '3.5'
services:
  bar:
    image: bar
    build:
      context: .
      dockerfile: Dockerfile

networks:
  default:
    name: dev_network
    driver: bridge

Starting up the foo service:

docker-compose build; docker-compose run foo
Building foo
Step 1/4 : FROM debian:stretch-slim
 ---> bd04d03c4529
Step 2/4 : RUN set -x  && apt-get update && apt-get install -y apt-utils
 ---> Using cache
 ---> e53a746ba26b
Step 3/4 : RUN set -x  && apt-get install -y iputils-ping
 ---> Using cache
 ---> 63e2377e85d7
Step 4/4 : ENTRYPOINT ["/bin/bash"]
 ---> Using cache
 ---> c304ddfa1035

Successfully built c304ddfa1035
Successfully tagged foo:latest
root@680d2ef987d2:/# 

Starting the bar service looks identical:

docker-compose build; docker-compose run bar
... same as above mostly

After starting the two services, the networks look like this:

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
95c4f247d652        bridge              bridge              local
13e26f1434ba        dev_network         bridge              local
5fc09d998133        host                host                local
23acbaf51f4e        none                null                local

And inspecting the dev_network shows:

docker network inspect dev_network

docker network inspect dev_network
[
    {
        "Name": "dev_network",
        "Id": "13e26f1434ba74c16964d29ceaa73eafd9df09622a1801c9fc9e49d2552273de",
        "Created": "2019-01-07T22:08:25.3589996Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.28.0.0/16",
                    "Gateway": "172.28.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "75cba11f489c8ad01ece0c5348d150fa6e64cdb5da31fe791e4f1c17284326c8": {
                "Name": "foo_foo_run_7faa90f193d0",
                "EndpointID": "f133df00bec7849c700669ef4395c5c45e82f6b6ab462f4f988508ac78d87d4b",
                "MacAddress": "02:42:ac:1c:00:02",
                "IPv4Address": "172.28.0.2/16",
                "IPv6Address": ""
            },
            "807fbb8527aacc5d5ac7ef35091ae589aa85a18401f99eb558bfbf07fa5826ef": {
                "Name": "bar_bar_run_45964b29fb9a",
                "EndpointID": "99001203fdb6f3f1e33b95cad53648c2a029dcda269a687f81ba443656d3d3c2",
                "MacAddress": "02:42:ac:1c:00:03",
                "IPv4Address": "172.28.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "dev_network",
            "com.docker.compose.project": "bar",
            "com.docker.compose.version": "1.23.2"
        }
    }
]

Docker does as you say: each compose.yml creates the declared private network. Just because they seem share the same name, doesn’t make them the same network.

If you want to have a shared network, you need to create it outside your compose.yml.
Usage: docker network create [OPTIONS] NETWORK

Depending whether you aim for a host spanning overlay network or a single host bridged network, you will want to use --driver bridge or --driver overlay.

You need to declare it inside your compose.yml with “external: true”:

networks:
  NETWORK:
    external: true

If you want to use a different network name inside the compose.yml as the existing external docker network, you can use “name: {external docker network}” as a sibling node to external to map those.

Using ping with a service name might not do what you expect. What you may want to do is ping the container name. For example, ping bar_bar_run_45964b29fb9a from foo would probably work.

In simple use cases it’s easy to assume services == containers but docker-compose.yml files can be used with docker stack commands which include things like number of replicas where you might have 3 instances of foo running and in that case, ping foo would not know which instance to ping.

However, a slight gotcha - pinging via container name won’t work on the default network, you’ll need to create your own. See https://docs.docker.com/v17.09/engine/userguide/networking/work-with-networks/#basic-container-networking-example section 8 (This functionality is not available for the default bridge network. Both container1 and container2 are connected to the bridge network, but you cannot ping container1 from container2 using the container name.)

You can also find the IP address of the container you wish to ping and ping the IP address directly you will probably see that it works. (In your example, ping 172.28.0.3 from foo to bar, and ping 172.28.0.2 from bar to foo.)

When you are using higher level networking commands such as HTTP requests the DNS service-to-service resolution will work as expected so you can still connect to other services via the service name, just not ping :slight_smile:

You are probably aware of this already but this sort of setup is easier if you put both services in the same docker-compose.yml file and then you only need to docker-compose up once. They will both join the default network without you needing to define anything.

I have to have separate docker-compose.yml files because the projects are in different git repos and different teams work on them.

I found a way to do it by changing the docker-compose run command to include the --name= argument, then I was able to conform the names for this test case

The way I am doing it, the network gets autocreated by the first container to start up. I prefer this as the order of starting up may vary