7. Docker Networking Explained | The Complete Docker Handbook.
Welcome to Article 7 of The Complete Docker Handbook.
In Article 6, we solved the data persistence problem using Volumes. Now we face another challenge: Communication.
By default, Docker containers are isolated. They run in their own little worlds.
- How does your frontend container talk to your backend container?
- How does your backend container connect to the database?
- How do you access your running container from your web browser?
If you try to ping one container from another out of the box, it might fail. If you try to access a port, it might be blocked.
In this article, we will demystify Docker Networking. You will learn how to connect containers, expose ports to the outside world, and use Docker's built-in DNS for seamless service discovery.
1. The Default Network Behavior
When you install Docker, it creates several default networks. You can see them by running:
Bashdocker network ls
Output:
Plain Text1NETWORK ID NAME DRIVER SCOPE 2a8f2c3d4e5f6 bridge bridge local 3b9g3d4e5f6g7 host host local 4c0h4e5f6g7h8 none null local
bridge(Default): When you run a container without specifying a network, it connects to this default bridge network. Containers on this network can access the outside world (internet), but they cannot resolve each other by name. You would need to use IP addresses, which change every time you restart.host: The container shares the host's networking namespace. No isolation. (Linux only).none: No networking at all.
> ⚠️ Critical Tip: For multi-container applications, do not use the default bridge network. Instead, create a User-Defined Bridge Network. This enables automatic DNS resolution.
2. Port Mapping (Exposing Services)
Containers have their own internal IP addresses (e.g., 172.17.0.2). Your computer cannot see these IPs directly. To access a web server running inside a container from your browser, you need Port Mapping.
The -p Flag
Syntax: -p :
Bashdocker run -p 8080:80 nginx
8080(Host Port): The port on your laptop/server. You visitlocalhost:8080.80(Container Port): The port the application is actually listening on inside the container.- What happens: Docker creates a firewall rule that forwards traffic from your computer's port 8080 to the container's port 80.
Common Port Mapping Scenarios
- Web Server:
-p 80:80(Standard HTTP) - Dev Server:
-p 3000:3000(Node.js React app) - Database:
-p 5432:5432(PostgreSQL)- Security Note: Be careful mapping database ports to the host. Anyone who can access your host IP can try to connect to your database. In production, databases should usually not have port mapping; they should only be accessible by other containers on the same network.
3. Container-to-Container Communication
This is the most important concept for microservices. How does the API container find the Database container?
The Problem with IP Addresses
If you start a database container, it might get IP 172.18.0.2. If you restart it, it might get 172.18.0.3. Hardcoding IPs in your application code is a bad idea.
The Solution: User-Defined Networks & DNS
When you create a User-Defined Bridge Network, Docker provides automatic DNS resolution. Containers can ping each other using their container names.
Practical Lab: Connecting App to DB
Let's create a network and run two containers that can talk to each other.
Step 1: Create a Network
Bashdocker network create my-app-network
Step 2: Run a Database Container
We'll name it db and attach it to the network.
Bash1docker run -d \ 2 --name db \ 3 --network my-app-network \ 4 -e POSTGRES_PASSWORD=secret \ 5 postgres
Step 3: Run a Web Container to Test Connection
We'll run a temporary container with ping installed to test connectivity.
Bash1docker run -it --rm \ 2 --network my-app-network \ 3 alpine ping db
Output:
Plain Text1PING db (172.18.0.2): 56 data bytes 264 bytes from 172.18.0.2: seq=0 ttl=64 time=0.15 ms 364 bytes from 172.18.0.2: seq=1 ttl=64 time=0.20 ms 4...
Success!
Notice we pinged db (the container name), not an IP address. Docker's internal DNS resolved db to the correct IP. Even if the database container restarts and gets a new IP, the name db will always resolve correctly.
4. Network Drivers Deep Dive
While bridge is the most common, you should know the others.
| Driver | Description | Use Case |
|---|---|---|
bridge | Private network on the host. Containers communicate via IP/DNS. | Default for single-host apps. |
host | Container uses the host's network directly. No port mapping needed. | High performance needs (e.g., monitoring agents). Less secure. |
none | No network interface. | Isolated security tasks. |
overlay | Connects multiple Docker daemons (swarm). | Docker Swarm / Multi-host clusters. |
macvlan | Assigns a MAC address to the container (appears as physical device). | Legacy apps needing direct physical network connection. |
5. Inspecting and Debugging Networks
When things go wrong (e.g., "Connection Refused"), use these commands to debug.
1. Inspect the Network See which containers are connected and their subnet.
Bashdocker network inspect my-app-network
Look for the Containers section to see IP addresses assigned.
2. Check Container IP
Bashdocker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
3. Test Connectivity from Inside If your app can't connect to the DB, exec into the app container and try to ping the DB.
Bashdocker exec -it ping db
6. Security Best Practices
- Isolate Tiers: Create separate networks for different tiers.
frontend-net: Connects Web + Load Balancer.backend-net: Connects Web + API + Database.- Result: The Load Balancer cannot directly access the Database.
- Don't Expose DB Ports: As mentioned earlier, avoid
-p 5432:5432for databases in production. Only connect them via internal networks. - Use Internal Flag: You can create a network with
--internalflag. This blocks access to the external internet entirely. Great for databases that don't need to download updates.Plain Text1bash 2docker network create --internal db-network
Summary Checklist
By the end of this article, you should be able to:
- Explain the difference between Host and Container ports.
- Create a user-defined bridge network.
- Connect containers using DNS names instead of IPs.
- Inspect network details using
docker network inspect. - Understand security implications of port mapping.
What's Next?
You now know how to manage containers, networks, and volumes manually using the CLI. But imagine running a stack with 5 containers, 3 networks, and 2 volumes. Typing all those docker run commands every time would be a nightmare.
Enter Docker Compose.
In Article 8, we will introduce the docker-compose.yml file. You will learn how to define your entire infrastructure (networks, volumes, services) in a single text file and launch it with one command.
Link: Read Article 8: Introduction to Docker Compose
Challenge: Create a custom network called web-net. Run an nginx container named web on it. Run an alpine container on the same network and curl the web container using its name (curl web).
Next Up: Introduction to Docker Compose