TT Lab
Get started
Learn Learning paths Courses

Docker Fundamentals

Create, Start, Exit — and Exit Codes

Continue in TT Lab

This lab runs on a real VM

This box is not a Pod but a virtual machine launched by KubeVirt. A separate Linux kernel runs in it, systemd actually manages services, and docker is a real Docker engine, not an imitation. A container started with docker run becomes a real process, and both docker exec and docker logs work as usual.

This lab used to run inside a Pod. That box had dropped every kernel capability, so the step that starts a container was blocked, and you learned by working around it and unpacking image archives by hand. The workaround is no longer needed.

There are two things to know.

Goal

You create container state transitions by hand and deliberately reproduce exit codes 143, 137 and 42, so that you learn their meaning by doing.

Why it matters

The report we get most often in operations is "the container died". But there are at least three ways to die, and each needs a completely different response. If the app ended by itself, you need to look at the code; if it ended after receiving SIGTERM, it was a normal deployment; and if it was killed by SIGKILL, nothing is left in the app log. The exit code is the cheapest signal for telling these three apart. Once you know one rule, that a value above 128 is 128 + 신호번호 (128 plus the signal number), you can read 143 = 128+15 = SIGTERM and 137 = 128+9 = SIGKILL right away.

Steps

  1. Create /root/dk2, and, using alpine:3.20, only create (do not start) a container named dk-life. The command is sleep 600.
  2. Start dk-life and put it in the running state.
  3. Using alpine:3.20, run dk-trap in the background so that it prints caught-term when it receives SIGTERM and ends with exit code 143. Then stop it normally.
  4. Using alpine:3.20, run dk-notrap in the background (the command is sleep 600) and stop it with a grace period of only 2 seconds. The exit code must be 137.
  5. Using alpine:3.20, run dk-fail so that it ends with exit code 42, and write only that number to /root/dk2/exit42.txt.
  6. Start the dk-restart container with the restart policy on-failure, at most 3 times.
  7. Take the process list from inside a container and save it to /root/dk2/pid1.txt. The PID column must be visible. This lab box is itself a container. If you run ps -e -o pid,ppid,comm here, you can confirm both that PID 1 is this container's main command and that only a handful of processes are visible.
  8. In /root/dk2/lifecycle.md, write the names and exit codes of the three containers dk-trap, dk-notrap and dk-fail, one per line.

Notes

Create without running

Create /root/dk2, and, using alpine:3.20, only create (do not start) a container named dk-life. The command is sleep 600.

run creates and starts right away. There is a separate subcommand that only creates. In this state there is no process yet.

Start the container you created

Start dk-life and put it in the running state.

Think about why creating and starting are separate. Once it starts, State.Pid gets an actual process number.

Exit cleanly on SIGTERM

Using alpine:3.20, run dk-trap in the background so that it prints caught-term when it receives SIGTERM and ends with exit code 143. Then stop it normally.

The shell has a builtin command for registering a signal handler. If the handler ends with the exit code you want, that value becomes the container exit code as is.

What happens without a handler

Using alpine:3.20, run dk-notrap in the background (the command is sleep 600) and stop it with a grace period of only 2 seconds. The exit code must be 137.

A PID 1 that has not registered a handler ignores SIGTERM. If you give a short grace period, you can see the result without waiting.

The exit code the application produced

Using alpine:3.20, run dk-fail so that it ends with exit code 42, and write only that number to /root/dk2/exit42.txt.

Dying from a signal and ending by the app's own choice have different exit code ranges. A value below 128 is one the app produced directly.

Restart only on failure

Start the dk-restart container with the restart policy on-failure, at most 3 times.

There are four restart policies. Choose the value that restarts only on failure, and with a limit on the count.

The process list inside a container

Take the process list from inside a container and save it to /root/dk2/pid1.txt. The PID column must be visible. This lab box is itself a container. If you run ps -e -o pid,ppid,comm here, you can confirm both that PID 1 is this container's main command and that only a handful of processes are visible.

If you list processes inside a container, the list is very short and you can immediately see what number 1 is. Do not run it on the host.

Build the exit code table

In /root/dk2/lifecycle.md, write the names and exit codes of the three containers dk-trap, dk-notrap and dk-fail, one per line.

Check the exit codes of the three containers with a real inspect and write them in the table. If you also write down why each value is what it is, it will help you later.