Docker Basics
Docker Networks
Docker networking provides an isolated communication layer for containers, allowing them to interact securely and predictably. Understanding these constructs is critical for building distributed applications where service discovery and traffic control define the architecture. You reach for custom networking when your application requires more than the default flat bridge, necessitating distinct subnets or service isolation.
The Default Bridge Network
When you install the runtime, a default bridge network named 'bridge' is automatically created. Every container you run without specifying a network flag joins this single shared environment. This works by utilizing a Linux bridge, which acts as a virtual switch between containers on the same host. The reason this exists is to provide 'out-of-the-box' connectivity without requiring manual configuration. However, relying on this default bridge is generally discouraged for production environments because all containers share the same network space, meaning they can communicate freely without strict policy enforcement. Furthermore, containers on this bridge cannot resolve each other by name; they must rely on fragile IP addresses, which are subject to change whenever a container restarts. For simple testing, this bridge is sufficient, but it lacks the robustness needed for complex applications that require distinct security boundaries and stable, predictable inter-service routing.
# Run a container on the default bridge
docker run -d --name web-server nginx
# Inspect the default bridge to see connected containers
docker network inspect bridgeUser-Defined Bridge Networks
A user-defined bridge network is the standard choice for multi-container applications running on a single host. Unlike the default bridge, these networks provide automatic DNS resolution, meaning you can address containers by their names instead of ephemeral IP addresses. This is a critical abstraction; it decouples your application code from the underlying networking topology. When you create a custom bridge, you isolate your traffic from other containers, providing a logical boundary that enhances security and organization. Furthermore, user-defined bridges support persistent connections, meaning containers can be attached and detached at runtime without needing to recreate the network. This flexibility allows for dynamic architecture where services scale horizontally. By creating a custom network, you ensure that only the containers explicitly connected to that network can communicate, effectively creating a firewall-like barrier that prevents unauthorized cross-talk between different applications running on the same host.
# Create a dedicated network for our application
docker network create app-network
# Run a database and a service on this network
docker run -d --name db --network app-network postgres
docker run -d --name app --network app-network my-apiContainer Network Aliasing
Network aliases allow you to map a specific hostname to a container, effectively giving it a friendly identity within the network scope. While container names are useful for identification, aliases provide an additional layer of abstraction that is essential when you have multiple instances or need to migrate services. By assigning an alias, you can decouple the service identity from the container name. This is particularly useful in load-balancing scenarios or blue-green deployments, where you might want a request to point to a generic host like 'database' regardless of which specific container instance is currently handling the traffic. The underlying DNS mechanism in the user-defined bridge resolves these aliases to the container's internal IP address, ensuring that service discovery remains seamless. This approach enables a service-oriented architecture where components only need to know the alias, not the individual container identifiers, facilitating easier updates and system maintenance.
# Connect a container to a network with a custom alias
docker run -d --name worker-1 --network app-network --network-alias backend my-worker
# Other containers can reach this service via 'backend'
docker exec app ping backendHost Networking Mode
The host networking mode removes network isolation between the container and the host machine. When you run a container with the host network, it shares the host's networking stack directly. This means that if the container binds to port 80, it is bound directly to the host's port 80. This mode is the highest-performance option because it bypasses the NAT (Network Address Translation) layer that bridges use, eliminating the overhead of packet routing and port mapping. You choose this mode when your application requires extremely low latency, needs access to specific system interfaces, or when the application is already managing its own network ports and needs full exposure to the host's physical network adapters. However, because the container occupies host ports, you lose the ability to easily run multiple instances of the same service on the same host without port collisions. This represents a trade-off between absolute throughput and the isolation benefits provided by bridged networking.
# Run a container using the host's network stack
docker run -d --network host --name performance-app my-optimized-serviceThe None Network Driver
The 'none' network driver essentially disables all networking for the container. When you attach a container to this network, it is stripped of its loopback interface and any external network connections, leaving it completely isolated. While this may seem counter-intuitive, it serves a specific and vital role in security-hardened environments. You would utilize this driver for containers running highly sensitive, compute-intensive tasks that require zero interaction with the outside world, such as data encryption or processing raw input files that are mapped in via volumes. By removing network access, you eliminate the entire surface area of network-based attack vectors, such as remote exploitation or data exfiltration. It ensures the container cannot communicate with external servers or even other local containers, providing a 'black box' environment. It is the ultimate expression of the principle of least privilege, ensuring that if a process does not need to talk to the network, it absolutely cannot.
# Run a secure, isolated job with no networking
docker run -d --network none --name sensitive-job my-processorKey points
- Docker uses virtual bridges to provide isolated communication channels between containers on the same host.
- User-defined networks enable automatic DNS resolution, allowing containers to locate each other by name.
- The default bridge network does not support container name resolution and is not recommended for production setups.
- Network aliases provide a flexible way to route traffic to specific containers without depending on static naming.
- Host networking mode offers maximum performance by bypassing the network translation layer, but restricts port flexibility.
- The 'none' network driver provides total isolation by stripping a container of all network interfaces.
- Choosing a network driver involves balancing the requirements for inter-container communication against the need for security isolation.
- Decoupling applications from specific network topologies is essential for scalable and maintainable containerized architecture.
Common mistakes
- Mistake: Relying on the 'default bridge' network for inter-container communication. Why it's wrong: You cannot use DNS-based service discovery by container name in the default bridge. Fix: Create and attach a custom user-defined bridge network.
- Mistake: Exposing all container ports to the host using -p. Why it's wrong: This bypasses internal network isolation and increases the attack surface. Fix: Only expose necessary ports and let containers communicate via private network aliases.
- Mistake: Assuming containers on different user-defined networks can communicate. Why it's wrong: Docker network isolation prevents cross-network traffic unless a container is explicitly attached to both. Fix: Attach the containers to a shared bridge network or use an overlay network.
- Mistake: Overlooking the 'host' network driver's impact on isolation. Why it's wrong: Using --network host removes network namespace isolation, meaning the container shares the host's IP and port range. Fix: Only use host mode when performance latency is critical and security isolation is not the primary requirement.
- Mistake: Forgetting to remove unused networks with 'docker network prune'. Why it's wrong: Accumulating hundreds of bridge networks leads to management overhead and potential IP address exhaustion in large environments. Fix: Regularly clean up networks that are no longer associated with active containers.
Interview questions
What is the purpose of Docker networks, and why do we need them?
Docker networks are essential because they provide isolated communication channels for containers. By default, containers are isolated, but they often need to talk to each other or external services. Using networks, such as the bridge network, allows containers on the same host to communicate using their container names as hostnames via the embedded DNS. Without networks, managing container-to-container connectivity would require manual port mapping, which is insecure and difficult to scale in a production environment.
Can you explain the default 'bridge' network driver in Docker?
The bridge network is the default driver used when you run a container without specifying a network. It acts as a virtual switch inside the Docker host. Every container attached to this bridge gets its own private IP address. The host machine acts as a gateway, using NAT to allow containers to reach the internet. While sufficient for simple use cases, you cannot use container name resolution on the default bridge; you must use user-defined bridge networks for that capability.
What is a user-defined bridge network, and why should you use it over the default bridge?
A user-defined bridge network is a custom network you create using 'docker network create'. The primary advantage over the default bridge is automatic service discovery via Docker's embedded DNS server. This allows containers to resolve each other by name, like 'db-service' instead of hardcoded IP addresses. Additionally, user-defined bridges offer better isolation, as only containers connected to the same custom bridge can communicate, whereas all containers on the default bridge can talk to each other regardless of need.
Compare the 'host' network driver with the 'bridge' network driver in Docker.
The host network driver removes network isolation between the container and the Docker host. When a container uses the host network, it shares the host's networking namespace, meaning it uses the host's IP and port range directly, which offers maximum performance by bypassing the NAT overhead. In contrast, the bridge driver provides network isolation and uses NAT, requiring port mapping to expose services. Use host mode when extreme network performance is required, but prefer bridge mode for security and container portability.
How does the 'overlay' network driver function in a multi-host environment like Kubernetes?
The overlay network driver creates a distributed network across multiple Docker hosts, which is the foundational technology for Kubernetes pod networking. It uses VXLAN encapsulation to wrap traffic inside standard UDP packets, allowing containers on different physical hosts to communicate as if they were on the same local subnet. In Kubernetes, this is critical because pods must be able to communicate across the entire cluster without needing explicit port mappings, regardless of which node they reside on.
Explain the concept of Container Network Interface (CNI) in the context of Kubernetes.
CNI is the standard specification for configuring network interfaces for Linux containers. In Kubernetes, the cluster doesn't implement networking natively; instead, it delegates network tasks to CNI plugins like Flannel, Calico, or Cilium. When a pod is scheduled, the kubelet calls the CNI plugin to assign an IP address and configure the routing table for that specific pod. This modular approach allows Kubernetes to support various networking models, from simple overlay networks to advanced Layer 7 network policies and high-performance routing.
Check yourself
1. Why is it recommended to use a user-defined bridge network instead of the default bridge network?
- A.It provides significantly better raw performance for disk I/O.
- B.It enables automatic DNS resolution for containers using their names.
- C.It automatically encrypts all traffic between containers without configuration.
- D.It allows containers to access the host file system directly.
Show answer
B. It enables automatic DNS resolution for containers using their names.
User-defined bridges enable embedded DNS, allowing containers to resolve each other by name. The default bridge does not support this. Performance is similar, encryption is not automatic, and file system access is unrelated to network type.
2. What happens when you run a container with '--network host'?
- A.The container is assigned a random private IP from the host's pool.
- B.The container gains full root access to the host's kernel modules.
- C.The container shares the network namespace of the host machine.
- D.The container is isolated from all external network traffic.
Show answer
C. The container shares the network namespace of the host machine.
The host network driver removes network isolation; the container uses the host's IP and ports directly. Option 1 is false because it doesn't get a separate IP; 2 is a security misunderstanding, and 4 is the opposite of the truth.
3. Two containers are on different user-defined bridge networks. How can they communicate?
- A.By using the host's IP address and published port.
- B.They can communicate automatically by default via the Docker daemon.
- C.By modifying the routing table on the host to bridge the two subnets.
- D.They can only communicate if one container is disconnected from its current network.
Show answer
A. By using the host's IP address and published port.
Containers on different networks are isolated. They can only interact via the host's IP on a published port. They don't communicate automatically (2), modifying routing tables (3) is not the correct Docker practice, and disconnecting (4) is a workaround, not a method of communication.
4. When using an overlay network in a Swarm cluster, what is the primary purpose of the 'control plane' traffic?
- A.To sync container logs across different nodes.
- B.To manage network configuration, discovery, and load balancing state across nodes.
- C.To ensure all container images are pre-pulled on every node.
- D.To bypass the need for an external load balancer.
Show answer
B. To manage network configuration, discovery, and load balancing state across nodes.
The control plane in an overlay network maintains the distributed state of the network. Logs (1), image pulling (3), and load balancing (4) are separate concerns managed by other Docker/Swarm components.
5. Which command would you use to verify which containers are attached to a specific user-defined network?
- A.docker inspect <network_name>
- B.docker network list <network_name>
- C.docker container ls --network
- D.docker network connect <network_name>
Show answer
A. docker inspect <network_name>
The 'docker inspect' command provides a detailed JSON output including a 'Containers' map. 'List' only shows network metadata, 'ls --network' is not a valid flag combination, and 'connect' is used to modify the network, not query it.