Docker Deep Dive · Prerequisites · P1 of 7

The Terminal & the Shell

Docker and Kubernetes are driven from one place: a shell. Every docker command, every Dockerfile RUN line, every kubectl exec lands you here — so before the whale, meet the three programs hiding behind your blinking cursor.

⏱ ~25 min hands-on · repo chapter p1-terminal-and-shell · cheatsheet: Linux & Shell · works on macOS, Windows, and Linux

prereq P1 / 7

Before you start — any OS is fine

You need Docker Desktop (or Docker Engine on Linux) installed and running — chapter 00-setup. Not because this lesson is about Docker, but because your computer probably isn't Linux — and even if it is, a container is the fastest disposable Linux machine you'll ever own. The main lab runs inside one, so it is identical on macOS, Windows, and Linux. Grab the chapter:

cd docker-deep-dive
git pull
cd p1-terminal-and-shell

Every docker … line in this course is the same on all three OSes. If you started the course here and haven't done Lesson 1 yet: whenever a docker run … line appears, just paste it — Lesson 1 explains every flag.

1Three programs pretending to be one

What you casually call "the terminal" is a sandwich of three very different programs:¹

on your computer (any OS) terminal emulator draws text · sends keystrokes shell: zsh · bash · PowerShell parses · finds programs · reports kernel: macOS · Windows · Linux runs programs · owns disk & network inside any container docker run -it · docker exec -it attaches the SAME terminal shell: bash (or sh) same shell for every learner kernel: Linux — always shared by every container — lesson 1 whatever your left side looks like, the right side is identical for everyone zsh and bash are POSIX cousins (skills transfer); PowerShell is its own language — so the labs live on the right
The sandwich, twice. docker exec -it web bash means: attach my terminal to a bash shell whose kernel is Linux. Your host's shell and kernel vary by OS; the container side never does — which is exactly why this course practices inside containers.⁴

Prompt anatomy. The shell signals who and where you are before every command. The convention survives across systems: zsh ends its prompt in %, bash in $ for a normal user — and # when you are root, the all-powerful admin user. (PowerShell writes PS C:\Users\you> — different costume, same job.) Inside containers you'll see # a lot; P2 explains why that matters.

2The 40 milliseconds after you press Enter

Type ls -l /var/log and hit Enter. Here's the round trip — step through it:²

terminal shell kernel ls -l /var/log⏎ raw text ls -l /var/log command flag argument find "ls" in PATH: /usr/local/bin ✗ /bin ✗ /usr/bin/ls ✓ run it ▶ ls starts read /var/log → entries drwxr-xr-x … apache2 -rw-r----- … syslog … a fresh prompt ▊ exit 0 the shell never reads the disk; the kernel never parses your typing — each layer does one job
  1. Enter pressed. The terminal understands none of it — it hands the raw text to the shell.
  2. The shell splits the line into words: a command, a flag, an argument. (Quoting rules — P3 — decide where words end.)
  3. The shell hunts for a program named "ls" through its PATH list of directories, left to right; first hit wins. P4 owns PATH.
  4. The shell can't execute anything itself — it asks the kernel to start /usr/bin/ls. (P5 gives this ask its real name: a syscall, execve.)
  5. Now ls does its one job: it asks the kernel for /var/log's entries. Only the kernel touches the disk.
  6. Output bytes flow back and the terminal draws them; ls exits with code 0 = success, and the shell prints a fresh prompt.
One command, three specialists. Keep this picture: it is exactly what happens for every RUN pip install … in a Dockerfile and every command you'll ever type into docker exec.²

3Command anatomy, and how to ask for help

command -f --long-flag argument1 argument2
# ls        -l          /var/log   → short flags stack: ls -lah = -l -a -h

Help systems, by where you're standing:

ls --help        # quick flag list — works in every container
man ls           # the full manual — on macOS & Linux hosts (Windows: Get-Help dir)
type ls          # what IS this command, really? (section 5 shows why this matters)

But try man ls inside a container and you get a surprise — images are stripped to stay small, so the manual pages simply aren't in there:

man ls
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, including manpages, you can run the 'unminimize'
command. You will still need to ensure the 'man-db' package is installed.

Rule of thumb: --help inside containers; man on a macOS/Linux host; Get-Help if you're in PowerShell.⁵

keyeffect (bash & zsh; most also work in PowerShell)
Tabcomplete the command/path — if it won't complete, it doesn't exist (your best typo detector)
↑ / ↓walk back through command history
Ctrl-Rsearch history as you type
Ctrl-Cinterrupt the running command (P4 reveals what this really sends)
Ctrl-Lclear the screen; history stays

4Lab A — move around, inside your Linux box

Your Linux playground — the one-liner of this whole phase

docker run -it --name linuxbox ubuntu:24.04 bash

A full Ubuntu, disposable, in about a second — and the same Ubuntu no matter what your host OS is. (New here? Don't worry what the flags mean — Lesson 1 explains them. For now: paste, and you're in Linux.)

Your prompt changes to something like root@bd5ceeacf242:/# — user root (that trailing #!), hostname = the container's ID. You are the admin of this tiny machine; P2 explores what that means. First, look at the land:

ls /
bin   dev  home  media  opt   root  sbin  sys  usr
boot  etc  lib   mnt    proc  run   srv   tmp  var

That's the standard Linux tree — /etc for config, /var for logs and data, /root is root's home. P2 gives you the guided tour; it's also exactly what a Docker image is. Now learn to move. The filesystem is one tree growing from the root, /. An absolute path starts there (/var/log); a relative path starts from where you are. Three shorthands: . here · .. up one · ~ your home.¹

pwd              # where am I? trust this, not the prompt
cd /var/log      # absolute: same result from anywhere
pwd
cd ~             # home again (plain cd does the same)
pwd
cd -             # bounce back to wherever you just were
/
/var/log
/root

Now build something. You'll make a small notes project, reorganize it, and tear part of it down — the exact moves you'll later do inside images:

cd ~
mkdir -p harbor-notes/docs harbor-notes/drafts    # -p makes parents too
cd harbor-notes
touch docs/setup.md docs/commands.md drafts/idea.txt
find .                                            # show the whole tree
.
./docs
./docs/commands.md
./docs/setup.md
./drafts
./drafts/idea.txt
cp -r docs docs-backup       # -r = recursive, needed for directories
mv drafts/idea.txt docs/idea.md   # mv moves AND renames — same command
rm -r docs-backup            # gone. no trash. no undo. read twice, then Enter
ls -l docs
total 0
-rw-r--r-- 1 root root 0 Jul 17 03:12 commands.md
-rw-r--r-- 1 root root 0 Jul 17 03:12 idea.md
-rw-r--r-- 1 root root 0 Jul 17 03:12 setup.md

Peek at details with ls -lah (long, all, human sizes) — for now read just names, sizes, dates. The cryptic rw-r--r-- column on the left is the entire subject of P2. To page through any long file: less filename — space scrolls, /word searches, q quits. Stay in the box (or hop back in with the same docker run line after an exit) — Lab B uses it.

5Your own terminal — three dialects, one common ground

Everything in Lab A also works natively on macOS and Linux, because their shells and tools come from the same POSIX family. But "the same family" is not "identical" — and Windows speaks a different language entirely. Ask your own shell what ls really is:

type ls          # bash/zsh (PowerShell: Get-Command ls)
# macOS (the instructor's themed zsh):
ls is an alias for eza --icons --grid --group-directories-first

# ubuntu:24.04 container (interactive bash):
ls is aliased to `ls --color=auto'

# Windows PowerShell (documented default):
Alias   ls -> Get-ChildItem

On all three systems, ls isn't plain ls. macOS setups often alias it to a modern tool like eza; Ubuntu quietly adds color flags; Windows PowerShell maps it to a completely different program, Get-ChildItem, whose flags share nothing with Unix ls.⁶ type (or Get-Command) is the truth-teller: it reveals aliases, builtins, and real binaries — ask it whenever a command behaves unlike the tutorial you're reading.

Even the "real" ls (aliases aside) differs by host — same name, three different programs:³

hostwhat answers to "ls"tell-tale
macOSBSD ls/bin/ls --version → unrecognized option — BSD has no --version
LinuxGNU ls (coreutils)ls --version → ls (GNU coreutils) …
Windows PowerShellGet-ChildItem — not ls at allUnix flags like ls -lah simply error

You only own one of those rows — no need to test the others. The check everyone can run, because every learner has the same container:

ls --version
ls (GNU coreutils) 9.4
Copyright (C) 2023 Free Software Foundation, Inc.

This is the point of the whole section: your host is a dialect; the container is the standard. Whatever terminal you own — zsh on a Mac, bash on Fedora, PowerShell on Windows — the linuxbox gives every learner the identical GNU/Linux environment, and that's the dialect Dockerfiles and Kubernetes manifests speak.

Windows users — two good options

Option 1 (used in this course): do everything inside the linuxbox container — your PowerShell only ever types docker … lines, which are identical on every OS. Option 2: install WSL 2 (Windows Subsystem for Linux) and get a genuine Ubuntu terminal on Windows — Docker Desktop on Windows already runs on WSL 2 under the hood, so you have half of it installed.⁷ Don't hand-translate the labs into PowerShell syntax — the flags genuinely don't map.

6Lab B — disposability, and your first graded exercise

exit                     # leave the shell → the container stops
docker rm linuxbox       # throw the whole machine away
docker run -it --name linuxbox ubuntu:24.04 bash
ls /root                 # … empty. your tree is gone

Fresh box, no harbor-notes. Containers forget — you met this in Lesson 1, and it's why anything worth keeping lives in an image (Lesson 3) or a volume (Lesson 5). Here it's a feature: you can never wreck this machine in a way docker rm won't fix.

Finish with the feedback loop. The chapter ships check.sh, a grader for the tree you built. Exit the box, then — from the chapter folder — start one that can see it (-v shares the folder at /labs; lesson 5 explains):

exit
docker rm linuxbox
docker run -it --rm -v "$PWD":/labs ubuntu:24.04 bash
docker run -it --rm -v "${PWD}:/labs" ubuntu:24.04 bash
cd /root
mkdir -p harbor-notes/docs harbor-notes/drafts
cd harbor-notes
touch docs/setup.md docs/commands.md drafts/idea.txt
cp -r docs docs-backup
mv drafts/idea.txt docs/idea.md
rm -r docs-backup
sh /labs/check.sh /root/harbor-notes
PASS  harbor-notes/ exists
PASS  docs/ exists
PASS  drafts/ exists
PASS  docs/setup.md exists
PASS  docs/commands.md exists
PASS  docs/idea.md exists (moved from drafts/ and renamed)
PASS  drafts/idea.txt is gone (it moved)
PASS  docs-backup/ is gone (rm -r cleaned it up)
----
8 passed, 0 failed
All good — tree matches the lab. ✔

Any FAIL line tells you which move to redo — fix it and run the grader again. (On a macOS/Linux/WSL host you can also do the whole lab natively and grade it with sh check.sh ~/harbor-notes — the grader is the same either way.)

You can now

7Check yourself

You type ls -l /var/log and press Enter. Which program splits the line into words and hunts for ls?

  1. the terminal emulator
  2. the shell itself
  3. the Linux kernel
  4. the ls program

Your current directory is /var/log. Where does cd ../tmp land you?

  1. /tmp
  2. /var/tmp
  3. /var/log/tmp
  4. /log/tmp

Inside the ubuntu:24.04 container, man ls prints a notice instead of the manual. Why?

  1. the image was minimized
  2. the network is offline
  3. man requires root privileges
  4. bash lacks man support

One line each: what do the terminal, the shell, and the kernel contribute when you run a command?

Terminal: draws text and forwards keystrokes — understands no commands. Shell: parses the line, finds the program via PATH, asks for it to run, reports the exit code. Kernel: actually starts the program and performs all disk, network, and memory work.

On three different machines, ls turned out to be an alias for eza (a Mac), for ls --color=auto (Ubuntu), and for Get-ChildItem (Windows PowerShell). What command exposes this, and why does it matter the moment you step into a container?

type (in bash/zsh; Get-Command in PowerShell) reveals what a name really resolves to — alias, builtin, or binary. It matters because your host's aliases and dialect don't exist inside a container: there you get plain GNU tools, so flags and output can differ from what your own terminal taught you to expect. Ask type before you rely on a command behaving the way a tutorial shows.

8Go deeper

Primary source: The Linux Command Line by William Shotts — free book at linuxcommand.org. Chapters 1–4 cover this lesson's ground with more leisure: what shells are, navigation, and file manipulation. It's the book this whole phase leans on. (Windows readers: everything in it applies inside your linuxbox or WSL.)

Next: that rw-r--r-- column you were told to ignore, the mysterious root, and the guided tour of /etc and friends — P2: Files, Permissions & root. The Linux tree you just glimpsed with ls / is, byte for byte, what a Docker image contains.

Stuck? Curious?

Bring questions to class, or open an issue on the course repo — include the command you ran and the output you got. The quizzes above are for self-checking: commit to an answer before revealing it, and re-try anything you missed tomorrow.

Sources

  1. Shotts — The Linux Command Line, ch. 1–4 (shell, navigation, file manipulation)
  2. GNU Bash Reference Manual — Command Search and Execution (word splitting, PATH lookup)
  3. GNU Coreutils manual (ls, cp, mv, rm semantics; GNU vs BSD flags)
  4. Docker Docs — docker exec (interactive shells in containers)
  5. Ubuntu — minimized images (why man pages are stripped)
  6. Microsoft Learn — about_Aliases (ls → Get-ChildItem in Windows PowerShell)
  7. Docker Docs — Docker Desktop WSL 2 backend (Windows runs containers via WSL 2)