Docker Community Forums

Share and learn in the Docker community.

Docker Networking Confusion

I have some confusion about Docker networking, and I was hoping that y’all could help clear me up. I presume I’m just not thinking about this the right way.

I am currently running a number of different services/appliances/etc, each in a different VM. We are trying to research and understand how to move these services to Docker in order to reduce our server overhead. Also, many of these VMs are “pets”, and Docker gives us a good way to move away from this model.

As a good example, we have our corporate wiki running in Mediawiki. On that VM, there are four services that support Mediawiki: Apache, MariaDB, Memcached, and Elastisearch. And all four have readily available container implementations, and I’ve tested them together, and it’s working fine.

The problem that I’m running into is networking from outside in the broader network into this cluster. And this is where I think my confusion is coming from.

When I publish the web ports on the Apache container, I want to be able to publish them on an arbitrary IP address different from the host. Similar to how I’m able to assign a VM an IP address different from the hypervisor. When I use a bridge network, the bridge allows the containers to talk to each other. I would assume there’s a way to assign a LAN IP address to the bridge, so that when I publish a port, it’s accessible on that IP.

As a more concrete example, I currently have 3 webservers, hosting a few different internal websites. Each webserver is a VM. Their IP addresses are 192.168.x.70, .x.71, and .x.72. If I move all three to containers on the same host, I want to be able to preserve this scheme: the containers support webserver 1 are in a bridge addressable at 192.168.x.70, webserver 2 at .x.71, etc.

But as it is currently, I can’t for the life of me figure out how to to this. In fact, it doesn’t appear that what I’m looking for is possible. But of course in my mind, what I’m asking for is obviously desirable, so I’m confused why I can’t figure this out.

Can anyone help my confusion?

The first step is to forget everything about VMs. Containers are not VMs, but isolated and ephemeral instances that run a single service. Second step, forget about IP addresses. If the containers have to communicated with each other, you can start them with the same compose file and they can immediately call each other. Take the compose file in the docs for the wordpress image as an example:

services:
  wordpress:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
    ...
  db:
    image: mysql:5.7
    ...

Here the wordpress service addresses the database as db and its port 80 is published as 8080 on the host.
If you have several web servers, then you can run a proxy like traefik in front of them.

The containers in the project you linked to are Linux containers. Docker on Windows runs Linux containers inside a Linux VM it creates using Hyper-V. Assuming you started those containers using the docker-compose file in the project, they will all be attached to default bridge network. I found this description of the docker0 bridge helpful

By default, the Docker server creates and configures the host system’s docker0 interface as an Ethernet bridge inside the Linux kernel that can pass packets back and forth between other physical or virtual network interfaces so that they behave as a single Ethernet network.

Since the containers are all attached to the same network, they are all able to access each other by IP address. If you were able to connect to the VM that Docker for Windows creates, you would be able to access those containers by their IP addresses as well.

The nginx container is accessible from localhost and from 127.0.0.1 because of port binding. When you create a container and publish (as the docker-compose file does on this line), Docker for Windows does some magic1 and requests made on that port are forwarded to the VM that’s running your containers, that VM then forwards the request to the container running nginx, which then responds to the request and you see the response in the browser.