Welcome back! In our last lesson, we mastered how to write a production-ready Dockerfile to build a small, fast, and secure image for a single service. This is a crucial first step. However, microservice architectures are, by definition, composed of multiple services that need to work together.
This brings us to a fundamental question: how do these isolated containers communicate with each other? In this lesson, we will answer that by exploring Docker networking. You will learn how to create a custom Docker bridge network, which enables your containerized services to discover and communicate with each other simply by using their names, a foundational requirement for building any multi-service application.
1. The Default Bridge Network and Its Limitations
When you run a container without specifying a network, Docker automatically connects it to a default network named bridge. While this provides basic connectivity, it has a significant drawback for microservices.
To understand this limitation, let's watch a short segment from the "Docker Networking Tutorial" video by Anton Putra.
Docker Networking Tutorial (Bridge - None - Host - IPvlan - Macvlan - Overlay)
This video introduces the default bridge network and its primary limitation for inter-container communication.
Watch the section that explains the default bridge network. Focus on the key takeaway: containers on this network can communicate, but they must use each other's IP addresses. The video highlights that this approach is not recommended, especially for production.
As the video explains, containers on the default bridge network can only find each other using their internal IP addresses. This is problematic for a microservices architecture for a few key reasons:
- IPs are Ephemeral: A container's IP address can change every time it is stopped and restarted. Hardcoding IP addresses in your application configuration would create an incredibly brittle system.
- Manual Configuration: Relying on IPs forces you to manually discover and configure the addresses of your services, which is impractical and doesn't scale.
Imagine your Order Service needs to call your Payment Service. If you have to look up the Payment Service's IP address every time it deploys, your system is fragile. What we need is a stable way for services to find each other, much like you use a domain name (e.g., google.com) instead of memorizing Google's server IP addresses. This is where user-defined networks come in.
2. The Power of User-Defined Bridge Networks
To solve the limitations of the default network, Docker allows you to create your own user-defined bridge networks. These custom networks are the recommended approach for production applications and provide several key advantages.
Differences between user-defined bridges and the default bridge
The official Docker documentation provides the best summary of why you should always use custom networks.
Read the section titled "Differences between user-defined bridges and the default bridge". Pay close attention to the first point: "User-defined bridges provide automatic DNS resolution between containers." This is the most critical feature for our purposes.
The ability for containers to resolve each other by name is a game-changer. When you place multiple containers on the same custom network, Docker provides a built-in DNS server. This server maps the container's name to its internal IP address automatically.
If you have a container named api and another named db on the same custom network, the api container can simply connect to the hostname db. Docker's internal DNS will resolve db to the correct IP address, no matter how many times the db container restarts.

3. Creating and Using a Custom Bridge Network
Let's see this in action. The process involves two simple steps: creating the network and then launching containers into it.
Step 1: Create the Network
You create a custom bridge network with the docker network create command.
docker network create my-app-net
This command creates a new, isolated network named my-app-net. You can verify it was created by running docker network ls.
Step 2: Run Containers on the Network
To attach a container to this network, you use the --network flag with the docker run command.
The following video provides a clear, practical demonstration of creating a network, launching two containers into it, and verifying they can communicate by name.
Docker Networking Tutorial (Bridge - None - Host - IPvlan - Macvlan - Overlay)
This part of the "Docker Networking Tutorial" shows a complete end-to-end example.
Watch the demonstration on creating and using a custom network. Observe how the docker network create command is used, how containers are launched with the --network flag, and most importantly, how curl successfully resolves the other container's name inside the network.
4. Hands-on Exercise: Service-to-Service Communication
Now it's your turn to build this yourself. We'll simulate a basic microservice setup: a web service and a database service.
-
Create the network:
First, create a network for our application. Let's call itecom-net.docker network create ecom-net -
Run the "database" service:
We'll use a standardpostgresimage to simulate our database. We'll name this containerdb.# We use -d to run it in the background # We set a password, which is required by the postgres image docker run -d \ --name db \ --network ecom-net \ -e POSTGRES_PASSWORD=mysecretpassword \ postgres:15-alpineThis container is now running on the
ecom-netnetwork and is reachable at the hostnamedb. -
Run a "client" service and test communication:
Now, let's run a temporary container to simulate another service (e.g., anapiservice) trying to connect to the database. We will use thealpineimage, which is very small, and attach a shell to it.# --rm automatically removes the container when we exit docker run -it --rm \ --network ecom-net \ alpine:latest sh -
Verify DNS resolution from inside the client container:
Once you are inside the alpine container's shell (you'll see a#prompt), you first need to install a tool to test network connectivity, likeping. Alpine's package manager isapk.# Inside the alpine container's shell apk add --no-cache iputilsNow, try to ping the database container using its hostname:
# Inside the alpine container's shell ping -c 3 dbYou should see a successful response, similar to this:
PING db (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.138 ms 64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.103 ms 64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.100 msThis proves that your client container was able to resolve the hostname
dbto the correct IP address and establish communication. You have successfully enabled service discovery! Typeexitto leave the alpine container. -
Clean up:
Finally, stop and remove thedbcontainer and the network.docker stop db docker rm db docker network rm ecom-net
Conclusion
You have now bridged a critical gap between running a single container and orchestrating a multi-service application. Manually managing individual containers and networks with these commands is insightful, but it can quickly become cumbersome.
Key Takeaways:
- The default
bridgenetwork is not suitable for microservices because it relies on unstable IP addresses for communication. - User-defined bridge networks provide crucial features for microservices:
- Network Isolation: Services are sandboxed within their own private network.
- Automatic DNS Resolution: Containers can reliably discover and communicate with each other using their container names as hostnames.
- The core commands are
docker network createto build the network anddocker run --network <name>to connect a container to it.
Preview of the Next Lesson
We've seen how to manually create a network and connect containers. In our next lesson, we will learn how to use Docker Compose. You'll discover how to define and run a complete multi-service application—including all its services, networks, and volumes—from a single, declarative docker-compose.yml file. This will automate everything we just did by hand and is the standard way to manage local development environments for microservices.