Day 11: Networking in Docker - Bridge, Host, None

Learning Objectives: By the end of this lesson, you will be able to:

  • Understand Docker’s networking architecture and default behaviors
  • Work with different network drivers: bridge, host, and none
  • Create and manage custom Docker networks
  • Configure container-to-container communication effectively

1. Welcome and Introduction (5 minutes)

Icebreaker Activity

Have you ever wondered how containers running on the same machine can talk to each other, or how they connect to the outside world? It’s like having multiple apartments in a building - each has its own space, but they all need to share utilities and communicate when needed. Today we’ll explore Docker’s networking magic!

Lesson Overview

  • Duration: 50-60 minutes
  • Prerequisites: Completion of Days 8-10, understanding of basic networking concepts
  • Materials Needed: Docker installed, multiple terminal windows, basic understanding of IP addresses

2. Learning Objectives and Session Outline (5 minutes)

What We’ll Cover Today:

  1. Docker Networking Fundamentals - How containers communicate by default
  2. Network Drivers - Bridge, host, none, and their use cases
  3. Custom Networks - Creating isolated network environments
  4. Container Communication - Name resolution and service discovery
  5. Network Inspection - Tools and commands for troubleshooting

Success Criteria:

By the end of this session, you should be able to design and implement network architectures for multi-container applications and troubleshoot connectivity issues.

3. Foundation Knowledge (15-20 minutes)

Docker Networking Architecture

Docker uses a pluggable networking system with different drivers for different use cases. When you install Docker, it automatically creates several networks that containers can use.

Real-World Analogy: Think of Docker networking like a smart building’s communication system. Each apartment (container) can have different ways to communicate - internal building phone system (bridge network), direct outside line (host network), or complete isolation (none network).

Key Networking Concepts:

  • Network Namespace: Isolated network stack for each container
  • Virtual Ethernet (veth) Pairs: Connect container to host network
  • Bridge Networks: Virtual switches connecting containers
  • Port Mapping: Exposing container ports to the host

Default Docker Networks

When Docker is installed, it creates three default networks:

1. Bridge Network (default)

  • Default network for containers
  • Provides isolation between containers and host
  • Containers can communicate with each other
  • Requires port mapping to access from host

2. Host Network

  • Container uses host’s network directly
  • No network isolation
  • Best performance, but less security
  • Port conflicts possible

3. None Network

  • Complete network isolation
  • No external connectivity
  • Useful for highly secure or batch processing containers

Key Terminology

  • Network Driver: Plugin that provides networking functionality
  • Bridge: Virtual switch connecting containers on same host
  • Port Mapping: Forwarding traffic from host port to container port
  • Service Discovery: Automatic resolution of container names to IP addresses
  • Network Namespace: Isolated network environment for containers

4. Detailed Explanation and Examples (25-30 minutes)

Working with Default Networks

Inspecting Default Networks

# List all networks
docker network ls

# Inspect default bridge network
docker network inspect bridge

# See network configuration of a container
docker inspect <container-name> | grep -A 20 "NetworkSettings"

Bridge Network Behavior

# Run containers on default bridge
docker run -d --name web1 nginx
docker run -d --name web2 nginx

# Check their IP addresses
docker inspect web1 | grep IPAddress
docker inspect web2 | grep IPAddress

# Test connectivity between containers
docker exec web1 ping web2  # This will fail - no name resolution on default bridge
docker exec web1 ping <web2-ip>  # This works with IP address

Custom Bridge Networks

Creating Custom Networks

# Create a custom bridge network
docker network create my-app-network

# Create network with specific subnet
docker network create \
  --driver bridge \
  --subnet=172.20.0.0/16 \
  --ip-range=172.20.240.0/20 \
  custom-network

# Run containers on custom network
docker run -d --name app1 --network my-app-network nginx
docker run -d --name app2 --network my-app-network nginx

# Test name resolution (works on custom networks!)
docker exec app1 ping app2  # Success! Name resolution works

Network Configuration Options

# Create network with custom configuration
docker network create \
  --driver bridge \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  --opt com.docker.network.bridge.name=my-bridge \
  advanced-network

Host Network Mode

# Run container with host networking
docker run -d --name host-app --network host nginx

# Container uses host's network directly
# No port mapping needed - nginx available on host:80
curl localhost:80

# Check network configuration
docker exec host-app ip addr show

Use Cases for Host Network:

  • High-performance applications
  • Applications that need to bind to specific host interfaces
  • Network monitoring tools
  • Legacy applications with complex networking needs

None Network Mode

# Run container with no networking
docker run -d --name isolated-app --network none alpine sleep 1000

# Container has no external connectivity
docker exec isolated-app ip addr show  # Only loopback interface

# Useful for batch processing or highly secure applications

Multi-Network Containers

# Create multiple networks
docker network create frontend
docker network create backend

# Run container connected to multiple networks
docker run -d --name multi-net-app --network frontend nginx

# Connect to additional network
docker network connect backend multi-net-app

# Verify connections
docker inspect multi-net-app | grep -A 5 "Networks"

Common Misconceptions

  1. Misconception: “Containers on the default bridge can communicate by name” Reality: Name resolution only works on custom networks, not the default bridge

  2. Misconception: “Host networking is always faster” Reality: Performance difference is usually negligible for most applications

  3. Misconception: “Port mapping is required for all container communication” Reality: Containers on the same network can communicate directly without port mapping

5. Live Coding Demonstration (20-25 minutes)

Example 1: Multi-Container Application with Custom Network

# Create application network
docker network create app-tier

# Run database container
docker run -d \
  --name postgres-db \
  --network app-tier \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=myapp \
  postgres:13

# Run application container
docker run -d \
  --name web-app \
  --network app-tier \
  -p 8080:3000 \
  -e DATABASE_URL=postgresql://postgres:secret@postgres-db:5432/myapp \
  node:18-alpine \
  sh -c "npm init -y && npm install express pg && node -e \"
    const express = require('express');
    const app = express();
    app.get('/', (req, res) => res.json({message: 'App running!', database: 'postgres-db'}));
    app.listen(3000, () => console.log('Server running on port 3000'));
  \""

# Test communication
curl localhost:8080

Explanation:

  • Both containers are on the same custom network
  • Application can reach database using container name postgres-db
  • Only the web application is exposed to the host via port mapping
  • Database is isolated and only accessible from within the network

Example 2: Network Isolation and Security

# Create separate networks for different tiers
docker network create frontend-net
docker network create backend-net

# Database (backend only)
docker run -d \
  --name secure-db \
  --network backend-net \
  postgres:13

# Application server (both networks)
docker run -d \
  --name app-server \
  --network backend-net \
  node:18-alpine sleep 1000

docker network connect frontend-net app-server

# Web server (frontend only)
docker run -d \
  --name web-server \
  --network frontend-net \
  -p 80:80 \
  nginx

# Verify isolation
docker exec web-server ping secure-db  # Fails - no connectivity
docker exec app-server ping secure-db  # Success - on same backend network

Key Points:

  • Database is completely isolated from frontend
  • Application server acts as intermediary
  • Defense in depth security approach
  • Network segmentation prevents lateral movement

Example 3: Service Discovery and Load Balancing

# Create network for load balancing demo
docker network create lb-demo

# Run multiple backend instances
docker run -d --name backend1 --network lb-demo \
  nginx:alpine sh -c "echo 'Backend 1' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"

docker run -d --name backend2 --network lb-demo \
  nginx:alpine sh -c "echo 'Backend 2' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"

docker run -d --name backend3 --network lb-demo \
  nginx:alpine sh -c "echo 'Backend 3' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"

# Simple load balancer using nginx
docker run -d --name load-balancer --network lb-demo -p 8080:80 \
  nginx:alpine sh -c "
    cat > /etc/nginx/conf.d/default.conf << EOF
upstream backend {
    server backend1:80;
    server backend2:80;
    server backend3:80;
}
server {
    listen 80;
    location / {
        proxy_pass http://backend;
    }
}
EOF
nginx -g 'daemon off;'
"

# Test load balancing
for i in {1..6}; do curl localhost:8080; echo; done

Debugging Network Issues

# Network troubleshooting commands
docker network ls
docker network inspect <network-name>

# Container network details
docker inspect <container> | grep -A 20 "NetworkSettings"

# Test connectivity between containers
docker exec <container1> ping <container2>
docker exec <container1> nslookup <container2>

# Check port binding
docker port <container>
netstat -tlnp | grep <port>

6. Hands-On Practice (30-40 minutes)

Exercise 1: Three-Tier Application (15 minutes)

Objective: Create a three-tier application with proper network isolation

Requirements:

  • Database tier: PostgreSQL (backend network only)
  • Application tier: Node.js API (both frontend and backend networks)
  • Presentation tier: Nginx reverse proxy (frontend network only, exposed to host)

Instructions:

  1. Create two custom networks: frontend and backend
  2. Set up PostgreSQL on backend network
  3. Create a simple API that connects to database
  4. Set up Nginx as reverse proxy on frontend network
  5. Test that each tier can only communicate with appropriate neighbors

Starter Code for API:

// api.js
const express = require('express');
const { Pool } = require('pg');

const pool = new Pool({
  host: 'postgres-db',
  database: 'myapp',
  user: 'postgres',
  password: 'secret',
  port: 5432,
});

const app = express();

app.get('/health', (req, res) => {
  res.json({ status: 'healthy', tier: 'application' });
});

app.get('/users', async (req, res) => {
  try {
    const result = await pool.query('SELECT NOW() as current_time');
    res.json({ message: 'Database connected!', time: result.rows[0].current_time });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.listen(3000, () => console.log('API server running on port 3000'));

Exercise 2: Network Performance Comparison (10 minutes)

Objective: Compare performance between different network modes

Instructions:

  1. Run the same container with different network configurations:
    • Default bridge network
    • Custom bridge network
    • Host network
  2. Measure response times using curl or ab (Apache Bench)
  3. Document the differences and explain the results

Test Commands:

# Install Apache Bench if needed
# Ubuntu: sudo apt-get install apache2-utils
# macOS: brew install httpd

# Performance test
ab -n 1000 -c 10 http://localhost:port/

Exercise 3: Network Troubleshooting Challenge (15 minutes)

Objective: Diagnose and fix networking issues in a broken setup

Scenario: You’ll be given a Docker Compose-like setup that has several networking problems:

  • Containers that can’t communicate
  • Services exposed on wrong ports
  • Name resolution failures

Your Task:

  1. Identify all networking issues
  2. Fix them using Docker networking commands
  3. Verify that all services can communicate properly

Broken Setup:

# This setup has intentional networking problems
docker network create problem-net

# Database (wrong network)
docker run -d --name db postgres:13

# API (missing environment variables)
docker run -d --name api --network problem-net \
  node:18-alpine sh -c "npm init -y && npm install express && node -e \"
    const express = require('express');
    const app = express();
    app.get('/', (req, res) => res.json({message: 'API works'}));
    app.listen(3000);
  \""

# Frontend (can't reach API)
docker run -d --name frontend -p 8080:80 nginx

# Fix these networking issues!

7. Common Pitfalls and Troubleshooting (10 minutes)

Frequent Mistakes

  1. Problem: Containers can’t communicate by name on default bridge Cause: Default bridge network doesn’t support automatic service discovery Solution: Use custom networks for name-based communication
# ❌ Won't work on default bridge
docker run -d --name app1 nginx
docker run -d --name app2 nginx
docker exec app1 ping app2  # Fails

# ✅ Works on custom network
docker network create my-net
docker run -d --name app1 --network my-net nginx
docker run -d --name app2 --network my-net nginx
docker exec app1 ping app2  # Success
  1. Problem: Port conflicts when using host networking Cause: Multiple containers trying to bind to same host port Solution: Use bridge networks with port mapping or different ports
# ❌ Second container will fail
docker run -d --network host nginx
docker run -d --network host nginx  # Port 80 conflict

# ✅ Use different ports or bridge networking
docker run -d -p 8080:80 nginx
docker run -d -p 8081:80 nginx
  1. Problem: Can’t reach container from host Cause: Forgetting port mapping on bridge networks Solution: Use -p flag for port mapping
# ❌ Not accessible from host
docker run -d --name web nginx

# ✅ Accessible on host port 8080
docker run -d --name web -p 8080:80 nginx

Debugging Network Issues

# Check container IP address
docker inspect <container> | grep IPAddress

# Test DNS resolution
docker exec <container> nslookup <target>

# Check network connectivity
docker exec <container> ping <target>

# Verify port bindings
docker port <container>

# Inspect network configuration
docker network inspect <network-name>

# Check if container is on expected network
docker inspect <container> | grep -A 10 "Networks"

Network Security Best Practices

# Use custom networks for isolation
docker network create --internal secure-backend

# Limit container capabilities
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx

# Use read-only containers when possible
docker run --read-only nginx

8. Best Practices and Professional Tips (10 minutes)

Industry Standards

Network Design Patterns

# Multi-tier application pattern
docker network create frontend --driver bridge
docker network create backend --driver bridge --internal

# Microservices pattern
docker network create service-mesh
docker network create database-tier --internal

Security Considerations

# Create internal networks for sensitive services
docker network create \
  --internal \
  --driver bridge \
  --subnet=172.25.0.0/16 \
  secure-internal

# Use specific subnets to avoid conflicts
docker network create \
  --subnet=10.1.0.0/24 \
  --gateway=10.1.0.1 \
  production-net

Performance Optimization

# For high-performance applications, consider host networking
docker run --network host high-performance-app

# Use custom MTU for specific network requirements
docker network create \
  --opt com.docker.network.driver.mtu=9000 \
  jumbo-net

Naming Conventions

# Use descriptive network names
docker network create myapp-frontend-prod
docker network create myapp-backend-prod
docker network create myapp-database-prod

# Use labels for organization
docker network create \
  --label environment=production \
  --label application=myapp \
  --label tier=frontend \
  prod-frontend

Production Considerations

  • Network Monitoring: Implement network monitoring for container communications
  • Service Mesh: Consider Istio or Linkerd for complex microservices
  • DNS: Use external DNS services for service discovery in large deployments
  • Load Balancing: Implement proper load balancing strategies

Next Steps in Your Learning Journey

  • Learn about Docker Compose networking (coming in later lessons)
  • Explore Kubernetes networking concepts
  • Study service mesh architectures
  • Practice with network policies and security

9. Summary and Review (5 minutes)

Key Takeaways

  1. Custom networks enable name resolution - Use them instead of default bridge for multi-container apps
  2. Network isolation improves security - Separate different tiers of your application
  3. Choose the right network driver - Bridge for most cases, host for performance, none for isolation

Quick Review Questions

  1. Why doesn’t name resolution work on the default bridge network?
  2. When would you use host networking mode?
  3. How do you connect a container to multiple networks?

Answers:

  1. The default bridge network doesn’t include Docker’s embedded DNS server for automatic service discovery
  2. For high-performance applications, network monitoring tools, or when you need direct access to host network interfaces
  3. Use docker network connect <network-name> <container-name> to add additional networks to a running container

For Instructors

Teaching Tips

  • Use network diagrams to visualize container communication
  • Demonstrate both working and broken network configurations
  • Show real-time network traffic using tools like tcpdump or wireshark
  • Emphasize security implications of different network choices

Assessment Ideas

  • Network design challenges for different application architectures
  • Troubleshooting exercises with intentionally broken configurations
  • Performance comparison assignments between network modes
  • Security audit of container network configurations

Adaptation Notes

  • For beginners: Focus on basic bridge networks and port mapping concepts
  • For advanced students: Introduce network plugins and custom drivers
  • Online delivery: Use screen sharing to show network inspection commands
  • Time management: Network troubleshooting can take longer - build in buffer time