TT Lab
Get started
Learn Learning paths Courses

Docker Fundamentals

What Is an Image and What Is a Container

Continue in TT Lab

One-line summary

An image is a file tree built from stacked read-only layers, and a container is an ordinary Linux process running with one writable layer added on top of it.

Why this is needed

The explanation "a container is a lightweight VM" has been around for a long time, but it gives the wrong prediction for almost every practical problem. If you run ps on the host, the nginx inside the container is right there.

48213 root      nginx
48261 systemd+  nginx

Seen from inside the container, the same processes appear as 1 nginx and 29 nginx. There are not two sets of processes; it is the same process seen from a different namespace. Checking the kernel version makes this even clearer. The host, an alpine container and an ubuntu container all report the same kernel. What an image provides is not a kernel but only a user-space file tree.

How it works

Layers are stacked with a union filesystem (overlayfs).

Layer structure of overlayfs — one writable layer sits on top of the read-only image layers and they appear as a single file tree called merged; a read walks down from the top, a write is a copy-up that copies the whole lower file upward, and a delete leaves only a whiteout marker so the original below stays intact

merged   <- 컨테이너가 보는 뷰
  ↑ upperdir  (쓰기 가능, 컨테이너 레이어)
  ↑ lowerdir  (읽기 전용, 이미지 레이어들이 겹겹이)

Every layer is named by the SHA-256 hash of its content. Identical content gets an identical name, so nothing is stored twice and integrity can be verified just by comparing hashes. This is also why an image ID looks like sha256:....

What gets decided the moment a layer is stacked

One instruction in a Dockerfile is one layer. And a layer is never erased. Most practical pitfalls come from these two sentences.

COPY secret.pem /tmp/secret.pem     ← 레이어 3에 파일이 들어간다
RUN ./setup.sh && rm /tmp/secret.pem  ← 레이어 4는 "지웠다" 는 기록일 뿐

In the final image /tmp/secret.pem is not visible, but it is still there in layer 3. Anyone can extract it by unpacking the image with docker save. Putting a secret into an image and then deleting it is not deleting it. Solve this with build secrets (RUN --mount=type=secret) or a multi-stage build.

For the same reason, the size does not shrink either.

RUN apt-get update && apt-get install -y build-essential   # +400MB
RUN apt-get purge -y build-essential                       # 여전히 +400MB

Only if you download and delete within a single RUN does the final state of that layer contain just the result.

What remains after you delete a container

When you delete a container, its writable layer disappears. So files you created inside a container vanish together with docker rm. This is why volumes are needed.

Storage location After the container is deleted Write performance When to use
Writable layer Gone Slow (copy-up) Temporary files
Anonymous volume Remains (hard to find because it has no name) Fast Something created by accident
Named volume Remains Fast Database data
bind mount The host file stays as it is Fast Source code during development

"copy-up" matters. In overlayfs, modifying a file in a lower layer copies the whole file into the upper layer. If you change one byte of a 1 GB file, 1 GB is copied. This is why you must not run a database in the container layer without a volume.

Image names and digests

Tags move. nginx:1.25 can be a different image today than it was yesterday. latest is even worse — it does not mean "newest"; it is merely the default name used when you omit the tag.

nginx:1.25                                    ← 움직인다
nginx@sha256:a1b2c3...                        ← 절대 안 움직인다

For production deployments, pin the image by digest. That way, "it worked yesterday but not today" can first be checked as "is it the same image as yesterday?".

What it looks like in the field

Because 100 containers that use the same base share the lowerdir as a whole, containers are created quickly and disk space is saved. Conversely, because of the copy-up cost, large writes such as database files must always go to a volume.

One more thing. If you confuse docker save with docker export, you lose a day. save exports an image including layers, tags and history, while export exports only a single filesystem snapshot of a container. If you import what you exported, it comes back to life with its ENTRYPOINT and ENV gone.

What you will do in the next lab

You will browse the image list yourself, start one container and check its log, and prove by image ID that a tag does not create a new image.