DEV Community

Cover image for Mount Namespaces and nsenter: Deep Dive
Ajinkya Singh
Ajinkya Singh

Posted on

Mount Namespaces and nsenter: Deep Dive

πŸš€ I'm Building My Own Container Runtime!

This is part of a complete series where I'm building Conti - a container runtime from scratch. Check it out on GitHub!

About This Series:

  • I'm sharing everything I learn while building my own container runtime
  • Most concepts come from videos, documentation, and LLM-assisted learning (for educational purposes)
  • Focus: Understanding through practice - raw Linux commands and practical implementation
  • Important: When building your own container, DON'T copy code from sources - it kills the fun! Write it yourself, break things, debug, and learn.

Why Build Your Own?

  • Deep understanding of how containers really work
  • Master low-level Linux concepts
  • Learn by doing, not just reading
  • It's incredibly fun when things finally click!

Understanding Mount Namespaces

We've already covered what namespaces are. Now let's dive deep into mount namespaces - one of the most critical components for container filesystem isolation.

Mount namespaces control which files and directories are visible to processes. They allow each containerized application to have its own view of the filesystem, preventing interference between applications.

The Isolation Problem

Without mount namespaces, all applications share the same filesystem view:

WITHOUT ISOLATION
─────────────────
πŸ“ /
β”œβ”€β”€ πŸ“ bin/
β”œβ”€β”€ πŸ“ etc/
β”œβ”€β”€ πŸ“ var/
└── πŸ“ sensitive-data/
    β”œβ”€β”€ webapp-secrets/      ← App A can see this
    β”œβ”€β”€ database-config/     ← App B can see this
    └── api-keys/            ← Everyone can see this

⚠️ Security Risk: All apps see all files
Enter fullscreen mode Exit fullscreen mode

With Mount Namespace Isolation

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  WebApp Namespace    β”‚     β”‚  Database Namespace  β”‚
β”‚                      β”‚     β”‚                      β”‚
β”‚  πŸ“ /                β”‚     β”‚  πŸ“ /                β”‚
β”‚  β”œβ”€β”€ bin/            β”‚     β”‚  β”œβ”€β”€ bin/            β”‚
β”‚  β”œβ”€β”€ lib/            β”‚     β”‚  β”œβ”€β”€ lib/            β”‚
β”‚  └── data/           β”‚     β”‚  └── data/           β”‚
β”‚      └── webapp/     β”‚     β”‚      └── db/         β”‚
β”‚                      β”‚     β”‚                      β”‚
β”‚  βœ… Isolated view    β”‚     β”‚  βœ… Isolated view    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

Understanding Mount Points

Before we go further, let's understand what "mounting" means.

What is Mounting?

Mounting is the process of making a filesystem accessible at a specific point in the directory tree. Think of your Linux system as a tree that can have different "branches" (filesystems) plugged in at various points.

Storage Device to Unified View

STORAGE DEVICE
──────────────
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Part 1 β”‚ β”‚ Part 2 β”‚ β”‚ Part 3 β”‚
β”‚ (sda1) β”‚ β”‚ (sda2) β”‚ β”‚ (sda3) β”‚
β”‚  ext4  β”‚ β”‚  swap  β”‚ β”‚ btrfs  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    ↓          ↓          ↓
  [root]    [swap]     [home]

         Kernel Magic ✨
              ↓

UNIFIED FILE SYSTEM
──────────────────
πŸ“ / (from sda1)
β”œβ”€β”€ πŸ“ bin/
β”œβ”€β”€ πŸ“ etc/
β”œβ”€β”€ πŸ“ home/ (mounted from sda3)
β”œβ”€β”€ πŸ“ var/
└── πŸ“ usr/
Enter fullscreen mode Exit fullscreen mode

The kernel stitches together multiple physical storage devices into one seamless directory tree.

Types of Mounts

1. Device Mount

Mounting a physical device or partition:

# Mount a USB drive
mount /dev/sdb1 /mnt/usb

# Mount a disk partition
mount /dev/sda3 /home
Enter fullscreen mode Exit fullscreen mode

2. Bind Mount

Mounting an existing directory to another location - making the same content appear in two places:

# Make /source/project appear at /workspace/active
mount --bind /source/project /workspace/active
Enter fullscreen mode Exit fullscreen mode

Bind Mount Visual:

BEFORE BIND MOUNT:
──────────────────
/project/           /workspace/
β”œβ”€β”€ src/            β”œβ”€β”€ temp/
β”œβ”€β”€ docs/           └── logs/
└── README

AFTER: mount --bind /project /workspace/active
────────────────────────────────────────────
/project/           /workspace/
β”œβ”€β”€ src/            β”œβ”€β”€ temp/
β”œβ”€β”€ docs/           β”œβ”€β”€ logs/
└── README          └── active/  ← Now shows
                        β”œβ”€β”€ src/     project
                        β”œβ”€β”€ docs/    content
                        └── README
Enter fullscreen mode Exit fullscreen mode

Creating Mount Namespaces

Basic Mount Namespace

# Create new mount namespace
sudo unshare --mount /bin/bash

# Now you're in an isolated mount namespace
# Any mounts you create are invisible outside
mkdir /tmp/isolated
mount --bind /home/user/data /tmp/isolated

# Exit the namespace
exit

# Check from parent - /tmp/isolated won't show the mount
ls /tmp/isolated  # Empty or doesn't exist
Enter fullscreen mode Exit fullscreen mode

Why This Matters for Containers

When a container starts, it needs its own filesystem view:

  • Container shouldn't see host mounts
  • Host shouldn't be affected by container mounts
  • Each container has its own /tmp, /var, etc.

Managing Namespaces with nsenter

Now that we understand mount namespaces, how do we interact with processes running inside them? Enter nsenter.

What is nsenter?

nsenter (namespace enter) allows you to enter the namespaces of an existing process. It's essential for debugging containers and understanding what's happening inside isolated environments.

Command Structure

nsenter --target <PID> [OPTIONS] <command>

# Common options:
--pid      # Enter PID namespace
--mount    # Enter mount namespace
--uts      # Enter UTS namespace
--net      # Enter network namespace
--all      # Enter all namespaces
Enter fullscreen mode Exit fullscreen mode

Practical nsenter Examples

Example 1: Viewing Container Processes

# Find the container's main process
ps aux | grep myapp
# Output: 4500 root /usr/bin/myapp

# Enter its PID namespace and list processes
sudo nsenter --target 4500 --pid ps aux

# You'll see only processes inside that namespace
# PID 1 will be the container's init process
Enter fullscreen mode Exit fullscreen mode

Example 2: Inspecting Container Filesystem

# Enter mount namespace to see what's mounted
sudo nsenter --target 4500 --mount df -h

# Or get a shell inside
sudo nsenter --target 4500 --mount /bin/bash
ls /  # You see the container's root filesystem
Enter fullscreen mode Exit fullscreen mode

Example 3: Full Container Debug Session

# Enter ALL namespaces of process 4500
sudo nsenter --target 4500 --all /bin/bash

# Now you're fully inside the container
hostname        # Container's hostname
ps aux          # Container's processes
ip addr         # Container's network interfaces
mount           # Container's mounts
cat /etc/hosts  # Container's host file

# Exit to return to host
exit
Enter fullscreen mode Exit fullscreen mode

Example 4: Resource Monitoring

# Monitor CPU/memory from inside container
sudo nsenter --target 4500 --pid top

# Check disk usage
sudo nsenter --target 4500 --mount du -sh /var/log

# Network connections
sudo nsenter --target 4500 --net netstat -tuln
Enter fullscreen mode Exit fullscreen mode

Complete Isolation Example

Let's create a container-like environment using multiple namespaces:

# Create PID, Mount, and UTS namespaces
sudo unshare --pid --mount --uts --fork /bin/bash

# At this point you're in isolated namespaces

# Set custom hostname (UTS namespace in action)
hostname my-container
hostname  # Shows: my-container

# Create isolated mount point
mkdir -p /tmp/container-root/{bin,lib,usr,var,tmp}

# Bind mount necessary directories
mount --bind /bin /tmp/container-root/bin
mount --bind /lib /tmp/container-root/lib

# Change root to our isolated filesystem
chroot /tmp/container-root

# Now you have:
# βœ… Isolated PID namespace
# βœ… Isolated mount namespace  
# βœ… Custom hostname
# βœ… Restricted filesystem view
Enter fullscreen mode Exit fullscreen mode

Entering This Container from Outside

# In another terminal, find the container process
ps aux | grep "my-container"
# Let's say PID is 6000

# Enter all its namespaces
sudo nsenter --target 6000 --all /bin/bash

# You're now inside the container
# Same view as if you were inside originally
Enter fullscreen mode Exit fullscreen mode

Key Concepts Recap

Mount Points

  • Mount Point: Directory where a filesystem is attached
  • Bind Mount: Making existing directory appear elsewhere
  • Root Filesystem: Primary filesystem containing system files

Mount Namespaces

  • Provide filesystem isolation
  • Allow processes to have different views of directory tree
  • Essential for container security

nsenter

  • Enters namespaces of running processes
  • Critical for debugging containers
  • Can enter specific or all namespaces
  • Must target a running process PID

Quick Reference Commands

# CREATE MOUNT NAMESPACES
unshare --mount /bin/bash                    # New mount namespace
unshare --mount --pid --fork /bin/bash       # Mount + PID namespaces

# MOUNT OPERATIONS
mount /dev/sdb1 /mnt/usb                     # Device mount
mount --bind /source /target                 # Bind mount
umount /mnt/usb                              # Unmount

# NSENTER - ENTER NAMESPACES
nsenter --target <PID> --mount /bin/bash     # Enter mount namespace
nsenter --target <PID> --pid ps aux          # Run command in PID namespace
nsenter --target <PID> --all /bin/bash       # Enter all namespaces

# VIEW NAMESPACE INFO
lsns                                         # List all namespaces
ls -l /proc/<PID>/ns/                        # View process namespaces
readlink /proc/<PID>/ns/mnt                  # Get mount namespace ID
findmnt                                      # Show mount tree
Enter fullscreen mode Exit fullscreen mode

Why This Matters for Conti

When building your container runtime, mount namespaces and nsenter are crucial:

  1. Isolation: Each container needs its own filesystem view
  2. Security: Prevent containers from accessing host files
  3. Debugging: Use nsenter to troubleshoot running containers
  4. Resource Management: Monitor container filesystem usage
  5. Root Filesystem: Create minimal root filesystems for containers

Building Conti? Star the repo on GitHub and share your progress!

Top comments (0)