docker_namespaces_explained

Home

Understanding Docker and Linux Namespaces

This guide explores how Docker utilizes Linux namespaces to provide container isolation. We'll use various command-line tools to inspect and interact with these namespaces.

1. Starting a Test Container

First, let's start a simple Nginx container in detached mode.

sudo docker run -d --name mynginx nginx
# Using '--name mynginx' for easier reference later
sudo docker ps
# Note the Container ID or name ('mynginx') from the output.

The question to consider: Can you curl inside this Nginx container from the host at this point without using docker exec or port publishing? (Typically, no, not directly to its container IP without knowing it or specific routing).

2. Inspecting Container Namespaces from the Host

2.1 Get the Container's Process ID (PID)

To inspect a container's namespaces from the host, we first need the PID of the main process running inside the container.

# Replace 'mynginx' with your container's name or ID if different
PID=$(sudo docker inspect --format '{{.State.Pid}}' mynginx)
# Example with a specific ID:
# PID=$(sudo docker inspect --format '{{.State.Pid}}' a8f058d6936c)

echo "The PID of the container's main process on the host is: $PID"
# You can see this process listed in the host's process list
ps aux | grep "$PID"

2.2 List Namespaces for the Container's Process

The lsns command can list the namespaces associated with a given PID.

2.3 Find Processes Sharing a Namespace

You can also use pgrep to find all processes (PIDs) that share the same specific namespace as the container's main process. For example, to find all PIDs in the same PID namespace:

3. Entering a Container's Namespaces with nsenter

The nsenter command allows you to run commands within one or more of a process's namespaces. This is a powerful way to "enter" a container's environment from the host without using docker exec.

  1. Enter all key namespaces of the container: The following command attempts to enter the mount, UTS (hostname), IPC, network, and PID namespaces of the container.

  2. Once inside the namespace (you'll see a new shell prompt): You are now operating within the container's context. For an Ubuntu/Debian-based container like Nginx, you can try:

Comparison with docker exec:docker exec is the standard Docker way to run commands inside a running container. nsenter is a lower-level Linux tool that achieves a similar result by directly manipulating namespaces.

4. Manipulating Network Namespaces

Let's demonstrate how to create a virtual network interface and move one end into the container's network namespace.

  1. Create a veth pair on the host: A veth (virtual Ethernet) pair consists of two connected virtual interfaces.

    Check the interfaces on the host:

  2. Move one end of the veth pair into the container's network namespace:

    The veth-guest interface will disappear from the host's interface list and now exist inside the container's network namespace. veth-host remains on the host.

  3. Configure the interface inside the container's namespace using nsenter: Enter the container's network namespace (and others for full context):

    Now, from the new shell prompt (inside the namespace):

    (Note: ifconfig is older; ip addr / ip link from iproute2 are preferred. Added iproute2 to the suggested install.)

  4. Verify with docker exec: You can also see the new interface using docker exec.

5. Advanced Exercise: Inter-Container Communication via Custom Network (Optional)

This section is for users comfortable with Linux networking. The goal is to enable communication between two containers using manually configured veth pairs and potentially a bridge.

  • Create a second container.

  • Create another veth pair, assign one end to the second container, and give it an IP address (e.g., 10.10.10.11/24) on the same conceptual subnet as the first container's veth-guest.

  • On the host, configure the host-side ends of the veth pairs (e.g., veth-host from the first pair, and the equivalent from the second). You might:

    • Bring up these host interfaces (e.g., sudo ip link set veth-host up).

    • Create a Linux bridge on the host (e.g., sudo ip link add name mybridge type bridge; sudo ip link set mybridge up).

    • Add the host-side veth interfaces to this bridge (e.g., sudo ip link set veth-host master mybridge).

  • Ensure IP forwarding is enabled on the host if traffic needs to be routed beyond the bridge:

  • Configure iptables or nftables if necessary, for example, to allow forwarding between the interfaces or to NAT traffic if containers need to reach outside. The original example snippet:

    (Corrected "mifgt" to "might". Changed <br> to list items. Clarified iptables rule example.)

This exercise demonstrates the underlying networking primitives that Docker's own networking commands (docker network create, etc.) abstract away.

Home

Last updated