The Riveting Tale of Docker Network Bridge & Docker Network Host

Lakshyajit Laxmikant
The Startup
Published in
6 min readJun 2, 2020

--

Well I suppose there’s no developer out there, who isn’t familiar with docker. If you have ever built a near-production level app, or worked in a team that does, you’re bound to have used it to deploy your apps/services in containers. I said “near-production” level because, in my opinion, that’s the stage when you start thinking about deploying your product somewhere in containers. We as developers, may have built numerous small apps, which mostly happen to be POCs for some bigger issue that we might be working on, but we don’t usually think about containers, unless it’s a project or app, that’s suppose to scale.

Enough said, today in this article I aim to put my thoughts regarding a very serious, yet quite interesting topic, i.e docker-networking. We all know that multiple containers communicate with each other through a network. Well there are different kinds of networking that we may require according to our app’s requirements/architecture(feel free to check them out on the official docs here, but in this article I will specifically discuss about two network modes, namely, bridge and host.

I would like to mention that, I created a spring-boot app and connected it to a mysql database for the purpose of my example. So for those of you, who would like to refer to the code while reading this article, you can checkout my repository below(I would suggest, please go through the article entire if you want to make complete sense of what’s in the repository):

So just to brief you about my project, it’s a simple spring-boot app, aimed to simulate CRUD operations. Here I have considered the idea of an online library, where, say an admin can Add, Remove, Edit and Lookup the book details. No fancy stuff, and the code is pretty straightforward, if you’re familiar with spring. Here is a snapshot of my controller class:

BookController Class(along with the spring folder structure)

And my data model looks like this:

Book Data Model (and my springboot folder structure)

Now, the reason I wanted to discuss these network-modes in specific, is because sometime back I was working on a project, where I faced a lot of trouble in starting my containers, where one of the microservices(spring) was linked to a mysql database (also running on a container). I found a work-around at that time, but was curious to find out, what might I be doing wrong. It turns out that, it was a misunderstanding of the working of these network modes. Now let’s understand the points that I learnt from the entire process(I organized my learning into points so that it will easier to comprehend and remember).

  1. The bridge network mode is the default mode that containers use when no network mode is specified.
  2. In case of bridge network mode, we need to do a port mapping in order to map the exposed ports of the containers to a specific port of the docker host.

For those you who are not clear what a docker host is, a Docker host is a physical computer system or virtual machine running Linux. This can be your laptop, server or virtual machine in your data center, or computing resource provided by a cloud provider. The component on the host that does the work of building and running containers is the Docker Daemon.

3. So in case of a bridge network mode, if the mapped ports are say 3308:3306, 3308 refers to our host machine’s port, while 3306 refers to the port exposed by the container.

4. Now since we have done the port mapping we need to specify the URL in our spring boot project(in our case, the URL on which mysql container is running) as something like this:

spring.datasource.url = jdbc:mysql://172.17.0.1:3308/library?allowPublicKeyRetrieval=true&useSSL=false

Please note that, 172.17.0.1 is default IP Address of a docker host. The other details in the snippet are pretty much self explanatory.

5. So in case of bridge networking, my docker-compose file looks like this:

version: '3'
services:
springsqlcrud:
build:
context: ./
dockerfile: Dockerfile
depends_on:
- mysql
restart: always
# network_mode: host
# hostname: localhost
ports:
- 8081:8081

mysql:
image: mysql:8
restart: always
ports:
- 3308:3306
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=library
container_name: mysqldb2
# network_mode: host
# hostname: localhost

And the dockerfile for my spring project looks like this:

#stage -1  for volume mounting maven dependencies
FROM maven:3.6-jdk-8 AS build
COPY pom.xml .
RUN mvn -Dmaven.repo.local=$MVN_LOCAL_REPO dependency:go-offline
COPY src src
RUN mvn -Dmaven.repo.local=$MVN_LOCAL_REPO -f pom.xml clean package -DskipTests

#stage -2 for creating the image of the project
FROM openjdk:8
EXPOSE 8081
COPY --from=build /target/springsqlcrud-0.0.1-SNAPSHOT.jar springsqlcrud.jar
ENTRYPOINT ["java", "-jar", "/springsqlcrud.jar"]

I think the commands/steps/multi-stage builds are simple to understand. So now all we need to do, is go to the root directory of our project in the terminal and type:

docker-compose up --build

This will build the spring and mysql containers after downloading the images(if not already present).

Note: The mysql container takes some time to start, but since our springboot project “depends” on it, it may so happen that, you’ll notice the spring project restarting a few times after failing. Actually, it’s waiting for the mysql container to start.

6. After both the containers start, you should see a screen similar to this:

Network mode — bridge

7. Yohoo! Now you can go ahead and test your application by using a software like postman to make API calls and perform CRUD operations on the database. If you wish to go checkout the database, I would suggest the following steps:

In your terminal, checkout the name of your mysql container, and then type the following one after the other:

docker exec -it <container-name> bashmysql -uroot -proot

Select the books table and checkout the data inside it.

8. Now let’s discuss about host networking mode. In case of host-networking, the containers instead of running on their own ports, map their ports to the host environment/machine’s ports. So here there is no need of a port mapping.

9. Here is what the docker-compose file looks like in case of host-networking mode.

version: '3'
services:
springsqlcrud:
build:
context: ./
dockerfile: Dockerfile
depends_on:
- mysql
restart: always
network_mode: host
hostname: localhost
# ports:
# - 8081:8081

mysql:
image: mysql:8
restart: always
# ports:
# - 3308:3306
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=library
container_name: mysqldb1
network_mode: host
hostname: localhost

10. Please note that the I have commented the port mappings we did previously. Now we have to modify our spring datasource url too. Since we are using host machine’s network(in this case it will be our laptop/desktop/workstation, while deploying to cloud, it may be a VM), we can mention localhost

spring.datasource.url = jdbc:mysql://localhost:3306/library?allowPublicKeyRetrieval=true&useSSL=false

11. The other steps of building and creating the containers remains absolutely same. After it runs successfully, you should see a screen similar to this:

Network mode host

NOTE: (Few important take aways):

  • Docker network host works well on a linux platform but not on a windows platform(I have no idea about MacOS, please feel free to check that out).
  • On a windows platform, the docker host’s IP is chosen randomly at runtime.
  • We can skip mentioning the “hostname: localhost” when using host networking mode.
  • On a windows platform the users, instead of using hostname, can use host.docker.internal(please check the official docs for windows platform configurations)

So that was all about these to networking modes in docker. I have been using docker since quite sometime now and I find it to be extremely useful. I hope that I will be able to clear the confusion which might have crept-in in some people’s minds(especially beginners) about these networking modes. FYI, the repository link whick I provided, contains the host-networking example in the master branch and the bridge-networking example in the network-bridge branch. Do check out both of them.

I like to work on different projects as a part of my learning process, even if I am already a full time working employee at IBM India Pvt. Ltd. I believe that there’s no subsitute to “learning by self” and when it comes to acquiring knowledge, well, “Sky is the limit”

Cheers!

--

--

Lakshyajit Laxmikant
The Startup

A tech-geek, curious creature, willing to learn new technologies to build interesting and intelligent systems...