Networking is a critical aspect of containerized applications. Understanding how Docker containers communicate with each other and with the outside world is essential for building robust, scalable applications. In this guide, we'll explore Docker networking concepts through practical examples and real-world scenarios.

Table of Contents #
- Introduction to Docker Networking
- Docker Network Types
- Basic Networking Commands
- Bridge Networks: The Default Choice
- Custom Bridge Networks and DNS
- Host and None Networks
- Multi-Container Communication
- Networking with Docker Compose
- Practical Examples: Web Application with Backend
- Network Isolation and Security
- Troubleshooting Network Issues
- Cleanup
- Conclusion
Introduction to Docker Networking #
Docker networking enables communication between containers and with external networks. It's the foundation for microservices architecture, allowing independent services to work together seamlessly. This guide is based on our Lab3 Networking Example from the Docker Practical Guide repository.
Docker's networking infrastructure provides:
- Container-to-container communication: Allowing containers to communicate with each other
- Container-to-host communication: Enabling access to the host system
- Container-to-external network communication: Connecting containers to the internet or other networks
- External-to-container communication: Allowing external systems to access services in containers
Docker Network Types #
Docker provides several network drivers to accommodate different use cases:
┌────────────────────────────────────────────────────────────┐
│ Docker Network Types │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ │ │ │ │ │ │
│ │ Bridge │ │ Host │ │ None │ │
│ │ Network │ │ Network │ │ Network │ │
│ │ │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ │ │ │ │ │ │
│ │ Overlay │ │ Macvlan │ │ Custom │ │
│ │ Network │ │ Network │ │ Plugins │ │
│ │ │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└────────────────────────────────────────────────────────────┘
- Bridge: The default network driver, creating a private network for containers on a single host
- Host: Removes network isolation, using the host's networking directly
- None: No networking (isolated containers)
- Overlay: Enables communication between containers across multiple Docker hosts
- Macvlan: Assigns a MAC address to containers, making them appear as physical devices on the network
- Network Plugins: Third-party plugins for custom networking solutions
Basic Networking Commands #
Let's start with the essential Docker networking commands:
# List all networks
docker network ls
# Inspect a network
docker network inspect bridge
# Create a custom network
docker network create --driver bridge my_network
# Connect a container to a network
docker network connect my_network container_name
# Disconnect a container from a network
docker network disconnect my_network container_name
# Remove a network
docker network rm my_network
# Remove all unused networks
docker network prune
Bridge Networks: The Default Choice #
When you don't specify a network, Docker attaches containers to the default bridge network:
# Run a container on the default bridge network
docker run -d --name webserver nginx
Characteristics of the default bridge network:
- Isolation: Containers on the bridge network are isolated from containers on other networks
- Communication: Containers on the same bridge network can communicate via IP addresses
- No Automatic DNS Resolution: Containers on the default bridge must use IP addresses to communicate
- Port Mapping: Containers can be exposed to the host using port mapping
Example of port mapping:
# Map container port 80 to host port 8080
docker run -d --name webserver -p 8080:80 nginx
# Access the container from the host at http://localhost:8080
Custom Bridge Networks and DNS #
Custom bridge networks provide additional features over the default bridge:
# Create a custom bridge network
docker network create app_network
# Run containers on the custom network
docker run -d --name web --network app_network nginx
docker run -d --name db --network app_network postgres
Key advantages of custom bridge networks:
- Automatic DNS Resolution: Containers can reach each other by name
- Better Isolation: Containers are isolated from containers on other networks
- On-Demand Connection: Easily connect and disconnect containers from the network
- Configuration Options: Control subnet, IP range, gateway, etc.
Example of DNS resolution:
# Container 'web' can communicate with 'db' by name
docker exec -it web ping db
Host and None Networks #
For specific use cases, you might need different network modes:
Host Network #
The host network mode removes network isolation between the container and the host:
# Run a container using the host network
docker run -d --network host --name direct_nginx nginx
When to use the host network:
- When maximum network performance is required
- When the container needs to directly access host network interfaces
- When avoiding port mapping configuration
None Network #
The none network mode disables all networking for a container:
# Run a container with no networking
docker run -d --network none --name isolated alpine sleep infinity
When to use the none network:
- For maximum isolation
- For batch processing that doesn't require network access
- When containers should be completely isolated for security reasons
Multi-Container Communication #
Let's look at how containers communicate in different scenarios:
Scenario 1: Containers on the Same Custom Network #
# Create a network
docker network create app_net
# Create two containers on the network
docker run -d --name web --network app_net -p 8080:80 nginx
docker run -d --name api --network app_net my-api-service
# Web container can communicate with API by name
docker exec -it web curl http://api:3000
Scenario 2: Containers on Different Networks #
# Create two networks
docker network create frontend_net
docker network create backend_net
# Create containers on separate networks
docker run -d --name web --network frontend_net -p 8080:80 nginx
docker run -d --name api --network backend_net my-api-service
# Containers can't communicate directly because they're on different networks
# Connect api to frontend_net to enable communication
docker network connect frontend_net api
# Now web can communicate with api
docker exec -it web curl http://api:3000
Networking with Docker Compose #
Docker Compose simplifies managing multi-container applications with network configuration:
version: "3"
services:
web:
image: nginx
ports:
- "8080:80"
networks:
- frontend
depends_on:
- api
api:
image: my-api-service
networks:
- frontend
- backend
depends_on:
- db
db:
image: postgres
environment:
POSTGRES_PASSWORD: mysecretpassword
networks:
- backend
volumes:
- db-data:/var/lib/postgresql/data
networks:
frontend:
backend:
volumes:
db-data:
Key networking features in Docker Compose:
- Automatic Network Creation: Creates default networks for the application
- Service Discovery: Containers can reference each other by service name
- Network Definition: Customizable network configurations
- Cross-Network Communication: Services can connect to multiple networks
Practical Examples: Web Application with Backend #
Let's implement a practical example based on our Lab3 Networking Example:
┌────────────────────────────────────────────────────────────┐
│ │
│ Microservice Architecture │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ │ │ │ │
│ │ Web Server │◄─────►│ API Server │ │
│ │ │ │ │ │
│ └─────┬───────┘ └─────┬───────┘ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ ▼ │
│ │ ┌─────────────┐ │
│ │ │ │ │
│ └──────────────►│ Database │ │
│ │ │ │
│ └─────────────┘ │
│ │
└────────────────────────────────────────────────────────────┘
Here's our Docker Compose file for a three-tier application:
version: "3"
services:
web:
build: ./web
ports:
- "8080:80"
networks:
- frontend
depends_on:
- api
api:
build: ./api
environment:
DB_HOST: db
DB_USER: postgres
DB_PASSWORD: example
DB_NAME: myapp
networks:
- frontend
- backend
depends_on:
- db
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: example
POSTGRES_DB: myapp
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
volumes:
db-data:
To run this application:
docker-compose up -d
This configuration creates:
- A frontend network for web and API communication
- A backend network for API and database communication
- Network isolation where the web service cannot directly access the database
Network Isolation and Security #
Proper network architecture enhances security by limiting container-to-container communication:
Best Practices for Secure Networking #
- Use Custom Networks: Create separate networks for different application tiers
- Principle of Least Privilege: Containers should only have access to the networks they need
- Expose Only Necessary Ports: Limit port publishing to what's absolutely required
- Use Network Aliases: Provide controlled service discovery
- Consider Network Policies: Implement additional network policies for fine-grained control
Example of isolating components:
version: "3"
services:
web:
image: nginx
ports:
- "80:80" # Only expose web to the outside world
networks:
- frontend
api:
image: my-api-service
# No exposed ports - accessible only from the frontend network
networks:
- frontend
- backend
db:
image: postgres
# No exposed ports - accessible only from the backend network
networks:
- backend
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
networks:
frontend:
backend:
Troubleshooting Network Issues #
Common network issues and solutions:
1. Container Can't Connect to External Networks #
Symptoms:
- Container can't access internet
- DNS resolution fails
Troubleshooting Steps:
# Test network connectivity
docker exec -it container_name ping 8.8.8.8
# Check DNS configuration
docker exec -it container_name cat /etc/resolv.conf
# Test DNS resolution
docker exec -it container_name nslookup google.com
Solutions:
- Check host's internet connection
- Verify Docker's DNS settings in daemon.json
- Restart Docker service
2. Containers Can't Communicate with Each Other #
Symptoms:
- Services can't connect by name or IP
- Connection timeouts between containers
Troubleshooting Steps:
# Verify network connectivity
docker exec -it container1 ping container2
# Check network configuration
docker network inspect network_name
# Verify container is connected to the expected network
docker inspect container_name | grep -A 10 "Networks"
Solutions:
- Ensure containers are on the same network
- Use proper container names or network aliases
- Check for firewalls or security software interfering
3. Port Mapping Not Working #
Symptoms:
- Can't access container service from host
- Connection refused errors
Troubleshooting Steps:
# Check published ports
docker port container_name
# Verify the container is listening on the expected port
docker exec -it container_name netstat -tuln
# Test connection from inside the container
docker exec -it container_name curl localhost:internal_port
Solutions:
- Ensure the application inside the container is listening on 0.0.0.0, not just 127.0.0.1
- Check for port conflicts on the host
- Verify host firewall settings
Cleanup #
After experimenting with Docker networking, it's important to clean up your environment to free up resources and avoid potential conflicts. Below are the steps to properly clean up the networking resources we created in this tutorial.
Cleaning Up Individual Containers and Networks #
# Stop and remove containers
docker stop container1 container2
docker rm container1 container2
# List all networks
docker network ls
# Remove custom networks
docker network rm my-bridge-network my-frontend-network my-backend-network
# Inspect if networks were properly removed
docker network ls
Disconnecting Containers from Networks #
If you need to disconnect a container from a network before removing it:
# Disconnect a container from a network
docker network disconnect my-bridge-network container1
Cleaning Up Docker Compose Resources #
If you used Docker Compose for the multi-tier application example:
# Navigate to the directory containing your docker-compose.yml file
cd /path/to/compose/directory
# Stop and remove containers, networks, and volumes
docker-compose down
# To also remove volumes (if you want to reset data)
docker-compose down -v
Removing Dangling Networks #
Sometimes networks may be left behind, especially if you stopped containers abruptly:
# Remove all unused networks
docker network prune
# You can combine with other prune commands
docker system prune
Verifying Clean State #
Confirm that your networking resources have been properly cleaned up:
# Check for remaining containers
docker ps -a
# Check for remaining networks (you should only see default networks)
docker network ls
Resetting Specific Scenarios #
For the specific examples we worked through:
# Clean up the web-api-db application
docker-compose -f multi-tier-docker-compose.yml down -v
# Clean up the basic container communication example
docker rm -f $(docker ps -aq --filter name=webapp)
docker network rm webapp-network
By properly cleaning up your Docker networking resources, you maintain a clean environment for future experimentation and avoid consuming unnecessary system resources.
Conclusion #
Docker networking is a powerful feature that enables containerized applications to communicate effectively while maintaining isolation and security. By understanding the different network types and how to configure them, you can build complex, multi-container applications that are both well-organized and secure.
In this guide, we've covered:
- The different types of Docker networks
- Basic networking commands
- Bridge network functionality
- Custom networks and DNS resolution
- Multi-container communication patterns
- Networking with Docker Compose
- Real-world application examples
- Network isolation and security best practices
- Troubleshooting common network issues
Armed with this knowledge, you can design and implement effective networking architectures for your containerized applications, ensuring they communicate efficiently and securely.
In the next article in our Docker Practical Guide series, we'll explore how to optimize Docker images using multi-stage builds, reducing image size and improving security. Stay tuned!
How are you structuring networks in your multi-container applications? Share your experiences or questions in the comments below!