Web development

Docker: the difference between an image and a container, explained with commands

What a Docker image is, what a container is and how they relate, with the basic commands to create, list, stop and remove each one, plus the most frequent mistakes.

A Docker image is an immutable, read-only template containing a file system with everything needed to run an application (code, dependencies, configuration). A container is a running instance of that image, with its own writable layer. The most useful analogy comes from object-oriented programming: the image is the class and the container is the object. From a single image you can start as many containers as you like, each isolated from the others.

If you are just starting with Docker, this distinction is the one that prevents most confusion: what gets downloaded, what runs, what takes up space and what is lost when you delete.

What an image is

An image is built in layers. Each instruction in a Dockerfile (FROM, RUN, COPY…) produces a layer, and layers are stacked: the bottom one is usually a base system (Debian, Alpine, Ubuntu), dependencies go on top and your application code goes at the top. Layers are read-only and shared between images: if ten images start from the same base, that base takes up disk space only once.

Images are identified by name and tag (node:22-alpine, nginx:1.27) and distributed through registries such as Docker Hub.

# Download an image
docker pull nginx:1.27

# List local images
docker images

# Build an image from the Dockerfile in the current directory
docker build -t my-app:1.0 .

# Remove an image (only if no container uses it)
docker rmi my-app:1.0

What a container is

A container is a process (or group of processes) that runs isolated from the rest of the system, using the image as its base file system and adding a writable layer on top. Everything the application writes while running (logs, temporary files, data) goes into that layer. When the container is removed, the writable layer disappears with it; the image stays intact.

# Create and start a container from an image
docker run -d --name web -p 8080:80 nginx:1.27

# List running containers (-a includes stopped ones)
docker ps
docker ps -a

# View logs and get a shell inside the container
docker logs web
docker exec -it web sh

# Stop, start again and remove
docker stop web
docker start web
docker rm web

docker run does two things at once: it creates the container (docker create) and starts it (docker start). That is why running docker run three times with the same image gives you three different containers, not one.

The relationship between the two, in a table

Image Container
What it is Read-only template Running (or stopped) instance of an image
Created with docker build, docker pull docker run, docker create
Listed with docker images docker ps -a
Removed with docker rmi docker rm
Changes while running? No Yes, in its writable layer
How many can exist? One per name:tag As many as you want per image

Where data lives: volumes

Since the writable layer dies with the container, any data that must survive (a database, files uploaded by users) has to live outside, in a volume or in a host directory mounted into the container:

# Volume managed by Docker
docker run -d --name db -v db-data:/var/lib/postgresql/data postgres:16

# Host directory (bind mount), handy in development
docker run -d --name web -v "$(pwd)/html:/usr/share/nginx/html:ro" -p 8080:80 nginx:1.27

With this you can remove and recreate the container without losing data. The volumes documentation details the differences between the two options.

Common mistakes

  1. Thinking docker stop frees space. A stopped container still exists with its writable layer. To free space you have to remove it with docker rm (or use docker run --rm so it deletes itself when it finishes).
  2. Storing data inside the container. It works until you recreate it. Use volumes from the start.
  3. Modifying a container and expecting the image to change. It does not. If a change should be part of the image, make it in the Dockerfile and rebuild. docker commit exists, but it produces non-reproducible images and is best avoided.
  4. Accumulating orphaned images and containers. docker system df shows how much they take up; docker system prune removes stopped containers, unused networks and dangling images (it asks for confirmation).
  5. Using the latest tag in production. latest changes over time; pin a specific version (node:22.12-alpine) so deployments are reproducible.

Conclusion

The image is the template; the container is the execution. Images are built and downloaded, containers are started, stopped and removed, and data that must last goes in volumes. With those three concepts clear, the rest of Docker (networks, Compose, registries) becomes combinations of the same ideas.

Sources and references

  1. Docker Docs: What is an image? docs.docker.com
  2. Docker Docs: What is a container? docs.docker.com
  3. Docker Docs: docker container run docs.docker.com
  4. Docker Docs: Dockerfile reference docs.docker.com
  5. Docker Docs: Volumes docs.docker.com

Web development

How to convert images to WebP (and when not to)

What WebP is, how much it saves over JPEG and PNG, how to convert images in the browser, the terminal or Node.js, and how to serve them with picture.

4 min read