跪拜 Guibai
← Back to the summary

Docker's Mental Model: Images Are Templates, Containers Are the Running App

Docker Study Notes (Part 1): Why Do We Need Images, Containers, and Repositories?

I used to have a very simple understanding of Docker:

Docker seems like a tool for "setting up environments."

After watching a Docker introductory video, I realized this understanding isn't wrong, but it's too crude.

The real problem Docker solves isn't "how to install Node, MongoDB, Nginx," but rather:

How to package the environment required to run an application into something reproducible, distributable, and repeatable.

This article won't rush into commands yet. First, let's clarify a few concepts that are easiest to mix up: Images, Containers, Docker Hub, and Image Repositories.


1. Where Does the Problem Come From?

Suppose I have a backend project that depends on these things:

On my own computer, all of these are configured, so the project runs.

But on another computer, these problems might arise:

node: command not found
mongo: command not found
Port is occupied
Environment variables not configured
Version mismatch
Dependency installation failed

This is the classic:

It works on my machine.

Docker's value is turning "my computer's environment" into a replicable runtime unit.


2. Image: Think of It as a "Snapshot of the Application Runtime Environment"

An image is not a running program; it's a static template.

You can understand it as:

Image = Base OS layer + Language runtime + Project code + Dependencies + Default startup command

For example:

docker pull nginx:alpine

What this command does is: download an nginx:alpine image from a remote image repository to the local machine.

This image already contains the environment needed to run Nginx.

But note:

The image itself does not run; it's just a template.

What actually runs is the container.


3. Container: A Running Instance Created from an Image

If an image is a "class," a container is an "object."

If an image is an "installation package," a container is a "running application."

For example:

docker run -d --name my-nginx -p 8080:80 nginx:alpine

This command means:

After running, visit:

http://localhost:8080

and you will see the Nginx page.

At this point, the local machine hasn't actually installed Nginx in the traditional sense; Docker ran it for us inside a container.


4. The Relationship Between Images and Containers

The easiest thing to confuse is this statement:

An image is not a container, and a container is not an image.

Their relationship can be viewed like this:

Dockerfile  --build-->  Image  --run-->  Container

Or:

Recipe       --cook-->  Dish Template   --serve-->  An actual dish
Dockerfile   --build-->  Image           --run-->    Container

You can create multiple containers from the same image:

docker run -d --name nginx-1 -p 8081:80 nginx:alpine
docker run -d --name nginx-2 -p 8082:80 nginx:alpine
docker run -d --name nginx-3 -p 8083:80 nginx:alpine

These three containers all come from the same image, but they are three independent running instances.


5. Docker Hub: The Public Image Registry

When we usually execute:

docker pull mongo:7

Docker defaults to looking for the mongo:7 image on Docker Hub.

You can think of Docker Hub as the npm of the Docker world:

npm registry   stores npm packages
Docker Hub     stores Docker images

Common images:

docker pull nginx:alpine
docker pull mongo:7
docker pull redis:7
docker pull node:22-alpine

These images have already been built by others, and we can use them directly.


6. Image Registries: Not Just Docker Hub

Docker Hub is the most common public registry, but it's not the only option.

In actual companies, you might also use:

In other words, an image registry is just a concept:

It is responsible for storing and distributing images.

Docker Hub is one implementation of it.


7. Why Can't You Pull Images on a Corporate Intranet?

If the company network cannot directly access Docker Hub, you might see errors like:

failed to resolve reference "docker.io/library/mongo:7"
failed to fetch oauth token
connect timeout

The root cause isn't that the Docker command is wrong, but rather:

The Docker client needs to access a remote image registry, but the corporate intranet doesn't allow it, or the proxy isn't configured correctly.

Common solutions include:

  1. Configure a Docker proxy.
  2. Use a corporate intranet image registry.
  3. On an external network machine, docker pull in advance, then docker save to export as a tar package, copy it to the intranet machine, and docker load.
  4. Have the company uniformly maintain base images.

For example, offline export:

# External network computer
docker pull mongo:7
docker save -o mongo-7.tar mongo:7

# Intranet computer
docker load -i mongo-7.tar

This approach is very suitable for environments that cannot directly access Docker Hub.


8. A Diagram to Understand Docker's Main Flow

        Write Dockerfile
              │
              ▼
        docker build
              │
              ▼
          Generate Image
              │
      ┌───────┴────────┐
      ▼                ▼
docker run       docker push
      │                │
      ▼                ▼
  Start Container  Upload to Image Registry
                       │
                       ▼
                  Other machines docker pull
                       │
                       ▼
                    docker run

This is Docker's core closed loop:

Write Dockerfile → Build Image → Run Container → Push to Registry → Other machines pull and run.


9. Summary of Part 1

This article only discusses the mental model.

A few concepts can be remembered like this:

Concept Role Analogy
Dockerfile Describes how to build an image Recipe
Image Static runtime environment template Installation package / Template
Container Instance after an image runs Running program
Docker Hub Public image registry npm registry
Private Image Registry Internal company image distribution center Company private npm source

The next part will start diving into commands: what exactly those flags like -p, -v, -e, --name, -d after docker run control.


References