Now let's learn how containers communicate with each other and the outside world.
Part 1: Understanding Container Networking Basics
The Networking Challenge
Simple Question: How do containers talk to each other?
Scenario:
You have:
├── Web application container (needs to talk to database)
├── Database container (needs to receive connections)
└── Redis cache container (needs to be accessed)
How do they communicate? 🤔
Container Isolation
Remember: Containers are ISOLATED
By default:
├── Each container has its own network stack
├── Own IP address
├── Own network interface
├── Cannot see other containers
└── Like separate computers on a network
Visual:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Container 1 │ │ Container 2 │ │ Container 3 │
│ │ │ │ │ │
│ IP: 172.17.0.2 │ │ IP: 172.17.0.3 │ │ IP: 172.17.0.4 │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
↑ ↑ ↑
└────────────────────┴────────────────────┘
Docker Network
How Containers Access the Outside World
Your Computer (Host):
Your Computer:
├── IP: 192.168.1.100 (on your home network)
├── Can access internet
└── Runs Docker
Container inside:
├── Has own IP: 172.17.0.2
├── Can access internet through host
└── Uses NAT (Network Address Translation)
Visual:
Internet
↕
Your Computer (192.168.1.100)
↕
Docker Network (172.17.0.0/16)
↕
Containers (172.17.0.2, 172.17.0.3, ...)
Part 2: Default Bridge Network
What is the Bridge Network?
Bridge Network = Default network Docker creates
When you run a container without specifying network:
docker run nginx
It automatically connects to the "bridge" network.
Viewing Networks
List all networks:
docker network ls
Output:
NETWORK ID NAME DRIVER SCOPE
a1b2c3d4e5f6 bridge bridge local
f6e5d4c3b2a1 host host local
1a2b3c4d5e6f none null local
Three default networks:
bridge:
├── Default network
├── Containers can communicate
└── Most commonly used
host:
├── Container uses host's network
├── No isolation
└── Advanced use case
none:
├── No network
└── Completely isolated
Inspecting the Bridge Network
docker network inspect bridge
Output (simplified):
[
{
"Name": "bridge",
"Driver": "bridge",
"Scope": "local",
"IPAM": {
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Containers": {
"abc123...": {
"Name": "container1",
"IPv4Address": "172.17.0.2/16"
}
}
}
]
Key Information:
Subnet: 172.17.0.0/16
└── IP range for containers
Gateway: 172.17.0.1
└── Docker's network gateway
Containers:
└── Lists all containers on this network
Testing Default Network
Run two containers:
# Container 1
docker run -d --name web1 nginx
# Container 2
docker run -d --name web2 nginx
Check their IPs:
docker inspect web1 | findstr IPAddress
Output:
"IPAddress": "172.17.0.2"
docker inspect web2 | findstr IPAddress
Output:
"IPAddress": "172.17.0.3"
Containers have different IPs on same network! ✓
Trying to Communicate (Default Bridge)
Access web1 from web2:
docker exec -it web2 bash
Inside web2 container:
# Try to ping web1 by IP
apt-get update && apt-get install -y iputils-ping
ping 172.17.0.2
# Output:
# PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
# 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.073 ms
# ✓ Can reach by IP!
# Try to ping by name
ping web1
# Output:
# ping: web1: Name or service not known
# ✗ Cannot reach by name!
Important Discovery:
Default bridge network:
✓ Containers CAN communicate by IP address
✗ Containers CANNOT communicate by name
└── Must use IP addresses (not convenient!)
Part 3: Custom Bridge Networks
Why Create Custom Networks?
Custom networks provide:
✓ Automatic DNS resolution (use container names!)
✓ Better isolation
✓ More control
✓ Can create multiple networks
└── Best practice for multi-container apps
Creating a Custom Network
Syntax:
docker network create NETWORK_NAME
Example:
docker network create my-network
Output:
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
↑
Network ID
Verify:
docker network ls
Output:
NETWORK ID NAME DRIVER SCOPE
a1b2c3d4e5f6 bridge bridge local
b2c3d4e5f6a7 my-network bridge local ← Your new network!
f6e5d4c3b2a1 host host local
1a2b3c4d5e6f none null local
Using Custom Network
Run containers on custom network:
# Container 1
docker run -d --name app1 --network my-network nginx
# Container 2
docker run -d --name app2 --network my-network nginx
Now test communication:
docker exec -it app2 bash
Inside app2:
# Install curl
apt-get update && apt-get install -y curl
# Access app1 by NAME!
curl http://app1
# Output:
# <!DOCTYPE html>
# <html>
# <head>
# <title>Welcome to nginx!</title>
# ...
# ✓ Works! Can use container name!
# Also try by IP
curl http://172.18.0.2
# ✓ Also works!
Magic! 🎉
Custom network provides:
✓ DNS resolution (container name → IP)
✓ No need to know IP addresses
✓ Use friendly names
└── Much easier to work with!
Real-World Example: Web App + Database
Scenario: Flask app needs to connect to MySQL
Step 1: Create custom network
docker network create app-network
Step 2: Run MySQL container
docker run -d \
--name mysql-db \
--network app-network \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=myapp \
mysql:8.0
Step 3: Create Python app
app.py:
import mysql.connector
import time
# Wait for MySQL to be ready
time.sleep(10)
# Connect using container name!
db = mysql.connector.connect(
host="mysql-db", # ← Container name!
user="root",
password="secret",
database="myapp"
)
cursor = db.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS users (id INT, name VARCHAR(50))")
cursor.execute("INSERT INTO users VALUES (1, 'Alice')")
db.commit()
cursor.execute("SELECT * FROM users")
for row in cursor:
print(f"User: {row[1]}")
db.close()
requirements.txt:
mysql-connector-python
Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]
Step 4: Build and run app
docker build -t my-app .
docker run --network app-network my-app
Output:
User: Alice
✓ App connected to database using container name!
Part 4: Port Publishing (Port Mapping)
Understanding Port Publishing
Problem:
Container running web server on port 80
├── Port 80 INSIDE container
├── Your computer can't access it
└── External users can't access it
Solution: Port Publishing
Map container port to host port:
Container port 80 → Host port 8080
Now:
├── Access localhost:8080 on your computer
│ ↓
├── Traffic goes to container port 80
└── Web server accessible! ✓
Port Publishing Syntax
Syntax:
docker run -p HOST_PORT:CONTAINER_PORT IMAGE
Examples:
# Map port 8080 to 80
docker run -p 8080:80 nginx
# Map port 3000 to 3000
docker run -p 3000:3000 node-app
# Map port 5432 to 5432
docker run -p 5432:5432 postgres
Multiple Port Mappings
docker run -p 8080:80 -p 8443:443 nginx
# ↑ ↑
# HTTP port HTTPS port
Viewing Port Mappings
docker ps
Output:
CONTAINER ID IMAGE PORTS NAMES
abc123def456 nginx 0.0.0.0:8080->80/tcp web
↑ ↑ ↑ ↑
│ │ │ └── Protocol
│ │ └── Container port
│ └── Host port
└── Listen on all interfaces
Port Binding to Specific Interface
Bind to all interfaces (default):
docker run -p 8080:80 nginx
# Accessible from anywhere
Bind to localhost only:
docker run -p 127.0.0.1:8080:80 nginx
# Only accessible from this computer
# Not accessible from network
Automatic Port Assignment
Let Docker choose the port:
docker run -P nginx
# ↑
# Capital P
Docker assigns random port:
docker ps
Output:
PORTS
0.0.0.0:32768->80/tcp
↑
Random port assigned
Access: http://localhost:32768
Part 5: Network Types in Detail
1. Bridge Network (Default)
What it is:
Default network type
├── Software bridge
├── Containers on same bridge can communicate
└── Most common type
When to use:
✓ Single host
✓ Multiple containers need to communicate
✓ Standard web applications
Example:
docker network create --driver bridge my-bridge
docker run --network my-bridge nginx
2. Host Network
What it is:
Container uses host's network directly
├── No network isolation
├── Container shares host's IP
└── Better performance (no NAT)
Example:
docker run --network host nginx
What happens:
Container:
├── Uses host's IP address
├── Port 80 on container = Port 80 on host
├── No port mapping needed
└── Cannot run multiple containers on same port
When to use:
✓ Need maximum network performance
✓ Network debugging
✗ Less isolation (security concern)
3. None Network
What it is:
No network at all
├── Completely isolated
├── No internet access
└── No container communication
Example:
docker run --network none nginx
When to use:
✓ Maximum isolation
✓ Security-critical containers
✓ Batch processing (no network needed)
4. Overlay Network (Advanced)
What it is:
Connects containers across multiple Docker hosts
├── For Docker Swarm
├── Multi-host networking
└── Advanced orchestration
Example:
docker network create --driver overlay my-overlay
When to use:
✓ Docker Swarm mode
✓ Multiple servers
✓ Distributed applications
Part 6: Connecting Containers to Multiple Networks
Container on Multiple Networks
A container can be on multiple networks!
Example:
# Create two networks
docker network create frontend
docker network create backend
# Run database on backend only
docker run -d --name db --network backend mysql
# Run API on both networks
docker run -d --name api --network backend nginx
docker network connect frontend api
# Run web on frontend only
docker run -d --name web --network frontend nginx
Result:
frontend network:
├── api ✓
└── web ✓
backend network:
├── api ✓
└── db ✓
Communication:
├── web → api (via frontend) ✓
├── api → db (via backend) ✓
├── web → db ✗ (not on same network)
└── Isolation achieved! ✓
Connecting/Disconnecting Networks
Connect container to network:
docker network connect NETWORK_NAME CONTAINER_NAME
Disconnect container from network:
docker network disconnect NETWORK_NAME CONTAINER_NAME
Example:
# Connect web to backend
docker network connect backend web
# Now web can access db!
# Disconnect web from backend
docker network disconnect backend web
# web can no longer access db
Part 7: DNS and Service Discovery
Automatic DNS Resolution
Custom networks provide automatic DNS:
Container names = Hostnames
my-app container:
├── Can be reached at: my-app
├── Can be reached at: my-app.my-network
└── Automatic DNS resolution
Testing DNS Resolution
Run containers:
docker network create test-net
docker run -d --name server1 --network test-net nginx
docker run -it --name client --network test-net ubuntu bash
Inside client:
# Install tools
apt-get update && apt-get install -y dnsutils curl
# Test DNS resolution
nslookup server1
# Output:
# Server: 127.0.0.11
# Address: 127.0.0.11#53
#
# Name: server1
# Address: 172.18.0.2
# ✓ Container name resolved to IP!
# Access server
curl http://server1
# ✓ Works!
Network Aliases
Give containers additional names:
docker run -d \
--name mysql-db \
--network app-net \
--network-alias database \
--network-alias db \
mysql
Now can access as:
mysql-db (container name)
database (alias)
db (alias)
Useful for:
✓ Backward compatibility
✓ Multiple names for same service
✓ Clearer naming
Part 8: Network Isolation Patterns
Pattern 1: Multi-Tier Application
Structure:
┌─────────────────────────────────────┐
│ frontend network │
│ ┌──────────┐ ┌──────────┐ │
│ │ Web │──────│ API │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────┬───────────┘
│
┌─────────────────────────┴───────────┐
│ backend network │
│ ┌──────────┐ ┌──────────┐ │
│ │ API │──────│ Database │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────┘
Isolation:
├── Web can only talk to API
├── API can talk to both
└── Database is hidden from Web
Implementation:
# Create networks
docker network create frontend
docker network create backend
# Database (backend only)
docker run -d --name db --network backend postgres
# API (both networks)
docker run -d --name api --network backend my-api
docker network connect frontend api
# Web (frontend only)
docker run -d --name web --network frontend -p 80:80 nginx
Pattern 2: Microservices Isolation
Each service on own network:
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Service A │ │ Service B │ │ Service C │
│ Network A │ │ Network B │ │ Network C │
└────────────┘ └────────────┘ └────────────┘
↓ ↓ ↓
┌────────────────────────────────────┐
│ API Gateway Network │
│ (Common Network) │
└────────────────────────────────────┘
Part 9: Practical Multi-Container Application
Building a Complete App
Let's build: Web App + API + Database
Step 1: Create networks
docker network create frontend
docker network create backend
Step 2: Run PostgreSQL
docker run -d \
--name postgres \
--network backend \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=myapp \
postgres:15
Step 3: Create API (api.py)
from flask import Flask, jsonify
import psycopg2
import os
app = Flask(__name__)
def get_db():
return psycopg2.connect(
host="postgres", # Container name!
database="myapp",
user="postgres",
password="secret"
)
@app.route('/api/users')
def get_users():
db = get_db()
cursor = db.cursor()
cursor.execute("SELECT version()")
version = cursor.fetchone()
return jsonify({"database": version[0]})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
requirements.txt:
flask
psycopg2-binary
Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY api.py .
CMD ["python", "api.py"]
Build and run:
docker build -t my-api .
docker run -d \
--name api \
--network backend \
my-api
# Connect to frontend too
docker network connect frontend api
Step 4: Create Web Frontend (index.html)
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<h1>Multi-Container App</h1>
<button onclick="fetchData()">Get Database Info</button>
<pre id="result"></pre>
<script>
async function fetchData() {
const response = await fetch('http://localhost:5000/api/users');
const data = await response.json();
document.getElementById('result').textContent = JSON.stringify(data, null, 2);
}
</script>
</body>
</html>
nginx.conf:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /api/ {
proxy_pass http://api:5000/api/;
}
}
Dockerfile:
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/conf.d/default.conf
Build and run:
docker build -t my-web .
docker run -d \
--name web \
--network frontend \
-p 8080:80 \
my-web
Step 5: Test the application
Open browser: http://localhost:8080
Click button → Data from database! ✓
Architecture:
User Browser
↓
Web Container (frontend network)
↓
API Container (frontend + backend networks)
↓
Database Container (backend network)
✓ Web can't directly access database
✓ API bridges the networks
✓ Proper isolation!
Part 10: Network Commands Reference
Complete Network Commands
# List networks
docker network ls
# Create network
docker network create NETWORK_NAME
# Inspect network
docker network inspect NETWORK_NAME
# Remove network
docker network rm NETWORK_NAME
# Remove all unused networks
docker network prune
# Connect container to network
docker network connect NETWORK_NAME CONTAINER_NAME
# Disconnect container from network
docker network disconnect NETWORK_NAME CONTAINER_NAME
Creating Networks with Options
# Create with custom subnet
docker network create --subnet=192.168.1.0/24 my-net
# Create with custom gateway
docker network create --gateway=192.168.1.1 my-net
# Create with driver
docker network create --driver bridge my-net
# Create with labels
docker network create --label env=prod my-net
Summary
What We Learned:
✅ Container networking basics
✅ Default bridge network
✅ Custom bridge networks
✅ DNS resolution in custom networks
✅ Port publishing/mapping
✅ Network types (bridge, host, none)
✅ Multiple networks per container
✅ Network isolation patterns
✅ Multi-container applications
✅ Service discovery
Key Concepts:
1. Use custom networks for container communication
2. Container names = Hostnames (with custom networks)
3. Port publishing exposes containers to outside
4. Multiple networks = Network isolation
5. Frontend/Backend pattern for security
Best Practices:
✓ Always use custom networks (not default bridge)
✓ Use container names (not IP addresses)
✓ Separate frontend/backend networks
✓ Only publish ports that need external access
✓ Use network aliases for flexibility
Excellent! You now understand Docker networking!
This completes Phase 6: Docker Networking!
🎉 Congratulations! You've completed the Basic Docker Roadmap!
You now know:
- ✅ Phase 1: Understanding Docker (Why, What, Architecture)
- ✅ Phase 2: Installation & First Steps
- ✅ Phase 3: Working with Images
- ✅ Phase 4: Creating Your Own Images (Dockerfile)
- ✅ Phase 5: Container Data Management (Volumes)
- ✅ Phase 6: Docker Networking
No comments:
Post a Comment