TT Lab
Get started
Learn Learning paths Courses

Docker Fundamentals

Running Your First Container

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

By handling images and containers by hand, you verify for yourself that a tag does not copy an image and that the inside and outside of a container see different file trees.

Why it matters

When people first meet containers, most of them try to memorize commands. But in practice, what gets you stuck is not the commands but the model. "I deleted the image but the container is still alive", "I changed the tag but the disk usage did not shrink", "the file exists inside the container but not on the host" — all of these are explained by one sentence: an image is a pile of read-only layers, and a container is a writable layer on top of it plus a process. So this lab is not about learning commands but about seeing that sentence with your own eyes.

Steps

  1. Create the /root/dk1 directory and save the list of images available in this box to /root/dk1/images.txt. Both the repository and the tag must be visible. docker images does not work in this box. Instead, each archive in /opt/images/*.tar has an index.json; if you read .manifests[0].annotations["org.opencontainers.image.ref.name"] in it, a name:tag such as docker.io/library/alpine:3.20 comes out as is — it is like looking one layer below to see where the Repository and Tag columns of docker images come from.
  2. From the alpine:3.20 image, create a container named dk-hello that prints hello-labhub, and keep the container even after it exits.
  3. Run nginx:1.27-alpine in the background with the name dk-web.
  4. In the nginx:1.27-alpine container, read /etc/os-release and save it to /root/dk1/web-os.txt. Read it with docker exec dk-web cat /etc/os-release. If you simply read this VM's /etc/os-release, you get Ubuntu and the check fails — that difference is exactly what the mount namespace does.
  5. Find the container IP address of dk-web and save only one line, the IPv4 address, to /root/dk1/web-ip.txt.
  6. To alpine:3.20, add one more name: labhub/base:v1.
  7. Delete the dk-hello container. Leave dk-web as it is.
  8. Fill in the three lines below with the actual values in /root/dk1/report.txt.
image=<dk-web 이 쓰는 이미지 이름:태그>
container=dk-web
state=<dk-web 의 현재 상태>

Notes

Save the image list

Create the /root/dk1 directory and save the list of images available in this box to /root/dk1/images.txt. Both the repository and the tag must be visible. docker images does not work in this box. Instead, each archive in /opt/images/*.tar has an index.json; if you read .manifests[0].annotations["org.opencontainers.image.ref.name"] in it, a name:tag such as docker.io/library/alpine:3.20 comes out as is — it is like looking one layer below to see where the Repository and Tag columns of docker images come from.

There is a subcommand that lists images. Do not just read the output on screen; keep it in a file with redirection. Not only the repository name but also the tag column must be left in it.

A container that runs once and ends

From the alpine:3.20 image, create a container named dk-hello that prints hello-labhub, and keep the container even after it exits.

If you give it a name, it is easier to find later. Note that if you add --rm it is deleted as soon as it finishes, leaving nothing to grade.

A container that keeps running in the background

Run nginx:1.27-alpine in the background with the name dk-web.

If you start it in the foreground, it holds your terminal. There is a flag that starts the container detached. It is normal for nginx to keep running without exiting.

Run a command inside a running container

In the nginx:1.27-alpine container, read /etc/os-release and save it to /root/dk1/web-os.txt. Read it with docker exec dk-web cat /etc/os-release. If you simply read this VM's /etc/os-release, you get Ubuntu and the check fails — that difference is exactly what the mount namespace does.

If you read /etc/os-release on the host, you get Ubuntu. You have to read it inside the container's mount namespace to get Alpine.

Find out the container's IP

Find the container IP address of dk-web and save only one line, the IPv4 address, to /root/dk1/web-ip.txt.

The inspect output is JSON. Dig into it with jq or use a --format template. Only the IP address must remain in the file.

Give the image another name

To alpine:3.20, add one more name: labhub/base:v1.

A tag does not copy an image. After adding the new name, compare the image IDs of the two names.

Clean up only the finished container

Delete the dk-hello container. Leave dk-web as it is.

A stopped container also holds on to its writable layer. You must keep the running one and delete only the finished one.

Turn the current state into a report

Fill in the three lines below with the actual values in /root/dk1/report.txt.

All three lines are checked against the actual inspect values. Do not guess; write values you confirmed with a command.