Practice brief
How Containers Actually Work Exercises
The TaskFlow API container has been running since Module 5. In Module 7 you look inside it — at the processes, the network interfaces, and the filesystem. Understanding what is actually there makes every docker exec command you run from here on deliberate rather than guesswork.
Build from scratch
Look Inside the Running Container
The taskflow-api container has been running since Module 5. From the outside it is just a process listening on port 8000. In this exercise you will get inside it using docker exec and inspect what is actually there: which processes are running, what network interfaces exist, and what the filesystem looks like. This is not a change to the TaskFlow setup — it is a deliberate investigation. Every docker exec command you run here is a skill you will use whenever you need to debug a container in the future.
Done when
Try it yourself first. Open the guided path if you get blocked.
Step 1 — Start the taskflow-api container
docker run -d --name taskflow-api -p 8000:8000 taskflow-api If taskflow-api is already running, skip this step. If it is stopped, run docker start taskflow-api. If it does not exist, this command creates it from the image you built in Module 5. Check with docker ps that it shows as Up before continuing.
Step 2 — List every process running inside the container
docker exec taskflow-api ps aux ps aux lists all running processes. Inside the container you will see very few — just the node process running api/server.mjs. Compare that to running ps aux on your host, which shows dozens of processes. The container cannot see the host's processes at all. Its own node process appears as PID 1 inside the container's namespace, even though on the host it has a much higher PID.
Step 3 — Inspect the network interface inside the container
docker exec taskflow-api ip addr ip addr shows every network interface. Inside the container you will see lo (loopback) and eth0. The eth0 address is the container's IP on Docker's internal bridge network — something like 172.17.0.2. This is not your host's IP address. The container has its own network stack, completely separate from the host and from other containers.
Step 4 — Read a file from the container's filesystem
docker exec taskflow-api cat /app/api/server.mjs This reads the application file from inside the container. The path /app/api/server.mjs is where your Dockerfile copied the code in Module 5 — WORKDIR /app, then COPY . . The container has its own isolated filesystem. Changes made inside the container do not affect the image or any other container started from it.
Step 5 — Confirm npm packages are installed inside the container
docker exec taskflow-api ls /app/node_modules | head -10 The .dockerignore you created in Module 6 excluded your local node_modules from the build context, but RUN npm install created a fresh set inside the image at build time. These are the packages the application actually uses. head -10 limits output to ten packages since there can be hundreds.
Step 6 — Open an interactive shell and explore freely
docker exec -it taskflow-api sh -it gives you an interactive terminal inside the container. You are now inside the same filesystem and process namespace you just inspected with individual exec commands. Run ls /app to see your project files. Run ps aux again. Run env to see environment variables. Type exit when done — the container keeps running after you leave.
Break-fix
The Process That Escapes the Container
A teammate ran a container with an extra flag to make debugging easier. They added --pid=host to the docker run command and exec-ed in. Inside the container, ps aux showed hundreds of processes — including processes from other containers and from the host itself. They thought this was normal. It is not. Reproduce this, see what the flag does, and explain why it breaks process isolation.
Reproduce this
docker run --pid=host -d --name taskflow-debug -p 8001:8000 taskflow-api
docker exec taskflow-debug ps aux You're done when
Show investigative hints
- Run ps aux inside the broken container and count the processes. Then remove it, start a normal container, and run ps aux again. The difference is the entire point of this exercise.
- The PID namespace is what makes a container's processes invisible to the host and to other containers. --pid=host removes that boundary entirely.
- A container running with --pid=host can see and signal any process on the host, including processes belonging to other containers. That is a serious security concern.
Show diagnosis and fix rationale
The --pid=host flag makes the container join the host PID namespace instead of getting its own isolated process namespace. That is why ps aux shows host processes and processes from other containers. Remove the flag and start the container normally. The container should then see only its own small process tree.