Skip to main content
RunBook Academy

← All labs in Docker & Containers

Lab · foundation · ~45 min

Lab 1: Your first container — manual nsenter and unshare

B · Nested virtualisationC · Simulation

Objectives

  • Create a new PID namespace with unshare
  • Inspect a process namespace with lsns
  • Enter a namespace with nsenter

This lab demystifies containers. You will build a “container” using only Linux kernel tools, then enter it using nsenter. By the end, the abstraction Docker provides will feel obvious.

Objective

Create a new PID namespace using unshare, see that PID 1 in the namespace is a child process, and then enter the namespace from another shell using nsenter.

Requirements

  • A Linux host with util-linux (provides unshare, nsenter, lsns).
  • A non-root user with sudo, OR a root user.

Architecture

flowchart TB
  subgraph Host["Host namespace (PID 1 = systemd)"]
    A1["PID 1: systemd"]
    A2["PID N: shell1"]
    A3["PID N+1: shell2"]
  end

  subgraph Unshare["New PID namespace (unshare)"]
    U1["PID 1: bash (the new init)"]
  end

Tasks

Task 1: Create a new PID namespace

unshare --pid --fork --mount-proc /bin/bash

Inside the new namespace:

  • Run ps aux. Notice that bash is PID 1.
  • Run echo $$. The shell’s PID is 1.

Task 2: Inspect namespaces from the host

In a second shell (still on the host, not in the unshare):

lsns -p $$
# Look at the PID namespace column
# Find the bash process from Task 1; its PID namespace is different

Task 3: Enter the namespace from another shell

Find the bash PID from Task 1 (look at ps auxf on the host). Replace <PID> with that value:

sudo nsenter -t <PID> -p -m -i -n -u -- /bin/bash

Inside the new namespace:

  • ps aux shows PID 1 = bash again. You’re in the same namespace.

Task 4: Verify with a different process tree

# In the original unshare namespace
sleep 1000 &

# From the nsenter shell, check
ps auxf
# The sleep process should be PID 2 in this view, not the host's view

Task 5: Clean up

# In each namespace
exit

# Verify all shells exited
ps -ef | grep sleep
# (should be empty)

Validation

You have successfully:

  • Created a new PID namespace using unshare.
  • Inspected namespaces from the host using lsns.
  • Entered an existing namespace from another shell using nsenter.
  • Verified the namespace isolation by checking process visibility.

Learning summary

A Linux namespace is a kernel feature for isolation. Docker uses the same kernel features, wrapped in a workflow that handles image management, networking, and volumes. The abstraction is convenient; the mechanism is the kernel.

Verification status

Last reviewed
2026-08-09
Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.