Understanding networks in Docker

Ishaan Ohri
ADGVIT
Published in
4 min readNov 30, 2020
Docker

What we’ll be doing?

We’ll be understanding the importance of networks in docker and how exactly a network is constructed automatically when using docker-compose compared to how it’s constructed manually when running containers through the native docker run command.

Why do we need a network?

Imagine a scenario where you have two services — Service A and Service B. You want Service B to be accessible only via Service A i.e. Service B cannot be directly accessed by a user. Therefore, if a user wants to interact with Service B, they must go via Service A.

A perfect example of this could be Service A being a Node.js express server and Server B is a SQL database.

This can be achieved by having both the services on the same network and making only the Node.js server accessible to the user. Although the SQL database will not be directly accessible to the user, the Node.js server being on the same network will be able to access it.

Let’s get started

Here, our focus is to understand networking in docker and not Node.js or SQL, therefore, to keep things simpler, we’ll replace the SQL database with another Node.js server. So now we have two Node.js servers, where only one server will be accessible to the user.

You can simply clone the project as we’ll be using the same hereafter. For those who aren’t familiar with Node.js, follow the setup guide in the project README and you should be good to go.

Generating images:

docker build -t server-a ./ServerAdocker build -t server-b ./ServerB

First, let's try setting up the containers using the native docker run command.

docker run -d -p 3000:3000 -e PORT=3000 --name container-a server-adocker run -d -e PORT=4000 --name container-b server-b

If you notice that in the above commands, we have done port mapping only for Server A and not for Server B, thus making only Server A publicly accessible.

Be sure to keep the image names and the container names as above, or else you’ll be required to change them at various other places as well.

Now head to your browser at http://localhost:3000

You would see something like this:

Now, as there exists no port mapping for Server B, therefore we can’t access it via the browser.

Let’s start setting up a docker network.

To view the already existing networks, execute the following:

docker network ls

You should expect a similar output. These are the already existing networks formed by docker.

NETWORK ID          NAME                DRIVER              SCOPE
d9582a30cb0f bridge bridge local
9af28926296f host host local
f95d0cd93e4b none null local

To create a new network with the name my-network, execute the following:

docker network create my-network

To attach the two containers to this network, execute the following:

docker network connect my-network container-adocker network connect my-network container-b

Now, if you run the following command again, you should see the network my-network in the output:

docker network lsNETWORK ID          NAME                DRIVER              SCOPE
d9582a30cb0f bridge bridge local
9af28926296f host host local
90264be9f504 my-network bridge local
f95d0cd93e4b none null local

Head back to your browser at http://localhost:3000

You would see something like this:

Here you can see a nested response from Server B inside the received response, showing that Server A was able to access Server B, without Server B being publicly accessible. Any other service on the same network would be able to access Server B as well.

All this was quite tedious, right?

Now let’s implement the same using docker-compose

We already have our images generated, if not execute the following:

docker build -t server-a ./ServerAdocker build -t server-b ./ServerB

Create a docker-compose.yml file as below in the root directory of the project.

Before executing the docker-compose, ensure you have stopped and removed the old containers.

Thereafter, execute the following:

docker-compose up

Head to your browser at http://localhost:3000

You would notice the same response that you received earlier (different timestamp, obviously xD).

Easy, right?

So now let’s understand what exactly happened behind the scenes.

Switch to a different terminal and execute the following:

docker network ls

You’ll get an output similar to this:

NETWORK ID          NAME                     DRIVER            SCOPE
d9582a30cb0f bridge bridge local
6ce2298f29b0 docker-network_default bridge local
9af28926296f host host local
12db76da1e64 my-network bridge local
f95d0cd93e4b none null local

Notice there is a new entry docker-network_default. This is the network created automatically by docker-compose to which all our containers defined in docker-compose.yml are attached.

What did we learn?

Other than the concept and requirement of networks in docker, we saw how easy it was to implement the same via docker-compose as compared to the native docker run commands.

Cheers!

--

--

Ishaan Ohri
ADGVIT
Writer for

Executive Head @ ADG VIT | Node JS Developer | Android Developer