DEV Community

Cover image for Docker Zootopia Networking
Manuel Artero Anguita 🟨
Manuel Artero Anguita 🟨

Posted on

Docker Zootopia Networking

I want to talk a little bit about Docker Compose, networking, and services calling each other. This is a super regular scenario that ‘ve already talked/posted/written, but I keep these post mostly for myself? if that makes sense.

So, from the beginning;

A docker-compose file, there is service-a (the main service) and service-b. I need service-a to ping to service-b.
And service-a has an environment variable to define the URL for service-b.

docker-network-1

The happy case works right out of the box; service-a can reach http://service-b:1080

why? cause there is a default Docker network configuration (I pretend that this is already written in my compose file)

networks:
  default:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

Which means:

  • Each service you define in the compose joins the network tagged default (its named like {folder-name}_default ).
  • Each service is automatically assigned automatically an IP address (like 172.x.x.x).
  • key thing: service-a can reach service-b by name cause this network already has a DNS resolution built-in

(I made up these IPs):

# DNS resolution example inside the Docker network
service-a -> 172.18.0.1:8080
service-b -> 172.18.0.2:1080
Enter fullscreen mode Exit fullscreen mode

Quick note!

Inside the Docker network they can call each other using these names… but from your machine you can’t use these names.

It’s like in Zootopia.

In Zootopia, a bunny can call another bunny "cute," but when other animals do it, it's a little… well, you know what I mean.

judy from zootopia

This is the same, you computer can’t use the name alias referring to service-a, it needs to use localhost and the forwarded port, that’s why we do this forwarding port thing like 4080:1080

docker-network-2


Anyway, this isn’t what I want to focus 👯,

because my particular use case has an additional key requirement:
service-a can not use http://service-b:1080 (there was an explicit code guard)  and NEEDED an actual ip-like address.

So, yay, easy right? just create an alias:

service-b:
  image: ...
  networks:
    default:
      ports:
        - 4080:1080
+     aliases:
+       - service-b.local
Enter fullscreen mode Exit fullscreen mode

So instead of

- http://service-b:1080
+ http://service-b.local:1080
Enter fullscreen mode Exit fullscreen mode

nick from zootopia

Except this needs an extra step.


Remember that DNS mapping we have by default? we neet to create a subnet and assign the IPs to each service manually….

…maybe there’s a more ‘DevOps-ish’ way to do this? but I find statically assigning the IPs pretty straightforward, im opened to alternatives:

services:
  service-a:
    image: ...
+   networks:
+     default:
+       ipv4_address: 172.21.0.10
    environment:
      SERVICE_B_URL: http://service-b:1080

  service-b:
    image: ...
    networks:
      default:
+       ipv4_address: 172.21.0.20
        aliases:
          - service-b.local
    ports:
      - 4080:1080

+ networks:
+   default:
+     ipam:
+       driver: default
+       config:
+         - subnet: 172.21.0.0/24

Enter fullscreen mode Exit fullscreen mode

IPAM means “Ey Docker, Im to assign manually the IPs”; The subnet part: 172.21.0.0/24 is creating a range of IPs between:

172.21.0.1 , 172.21.0.2 , 172.21.0.3172.21.0.254

And I assign each service… honestly, somewhat random (.0.10, 0.20).


Just one thing left, the DNS; we need to tell service-a to map the name and the IP:

  service-a:
    image: ...
    networks:
      default:
        ipv4_address: 172.21.0.10
+   extra_hosts:
+     - "service-b.local:172.21.0.20"
    environment:
      SERVICE_B_URL: http://service-b:1080
Enter fullscreen mode Exit fullscreen mode

And that’s it. Happy ending. service-a can now reach service-b using the name service-b.local, and everything works inside the Docker network.

docker-network-3

Top comments (0)