Introduction

In the previous chapter, we covered the basics of Docker Engine installation and its architecture. Now, it’s time to dive into the core concepts that make Docker so powerful: Images and Containers. These two fundamental building blocks are often confused, but understanding their distinct roles and how they interact is crucial for anyone looking to leverage Docker effectively.

This chapter will demystify Docker Images and Containers, explain their relationship, and demonstrate how to manage them using basic Docker commands. By the end, you’ll have a solid grasp of what they are, what they do, and how they form the backbone of Dockerized applications.

Main Explanation

What is a Docker Image?

A Docker Image is a lightweight, standalone, executable package that includes everything needed to run a piece of software, including the code, a runtime, libraries, environment variables, and configuration files. Think of an image as a blueprint or a template.

  • Read-Only Template: Images are immutable. Once created, they cannot be changed. This ensures consistency across different environments.
  • Layered File System: Images are built up from a series of layers. Each layer represents an instruction in the image’s Dockerfile (which we’ll cover in detail later). This layering allows for efficient storage and distribution, as common layers can be shared between images.
  • Portability: An image contains all dependencies, making it highly portable. You can build an image once and run it anywhere Docker is installed.
  • Origin: Images can be pulled from public registries like Docker Hub, private registries, or built locally from a Dockerfile.

What is a Docker Container?

A Docker Container is a runnable instance of a Docker Image. If an image is a blueprint, a container is the actual house built from that blueprint. When you run an image, Docker creates a container, which is an isolated environment where your application executes.

  • Runtime Instance: Containers are the actual execution environments for applications. You can have multiple containers running from the same image, each isolated from the others.
  • Isolated Environment: Each container runs in isolation from other containers and the host system. This isolation includes its own process space, network interface, and file system.
  • Read-Write Layer: While the image itself is read-only, a container adds a thin, writable layer on top of the image’s file system. All changes made by the running application within the container are stored in this layer.
  • Lifecycle: Containers have a lifecycle: create, start, stop, pause, and remove.

Image vs. Container: The Core Difference

FeatureDocker ImageDocker Container
NatureBlueprint, template, staticRuntime instance, executable, dynamic
StateRead-only, immutableRead-write layer on top of image
StorageStored as a series of layersIsolated runtime environment
PurposePackaging applications and their dependenciesRunning applications in isolation
CreationBuilt from a Dockerfile or pulled from a registryCreated and started from an image
AnalogyA class definition (programming), a cookie cutterAn object instance, a cookie

Key Concepts

  • Dockerfile: A text file that contains all the commands a user could call on the command line to assemble an image. It defines the base image, adds files, sets environment variables, and specifies the command to run when the container starts.
  • Docker Hub: A cloud-based registry service provided by Docker for finding and sharing container images. It’s the default registry for Docker.
  • Registry: A repository for storing and distributing Docker Images. Docker Hub is the most popular public registry, but private registries can also be used.

Examples

Let’s explore some basic Docker commands to manage images and containers.

1. Pulling a Docker Image

To download an image from Docker Hub to your local machine:

docker pull ubuntu:latest

This command pulls the ubuntu image with the latest tag. If no tag is specified, latest is assumed by default.

2. Listing Docker Images

To see all images currently stored on your local machine:

docker images

You’ll see a table with image details like REPOSITORY, TAG, IMAGE ID, CREATED, and SIZE.

3. Running a Docker Container

To create and start a container from an image:

docker run hello-world

This command will:

  1. Check if the hello-world image exists locally. If not, it pulls it from Docker Hub.
  2. Creates a new container from that image.
  3. Runs the command specified in the image (in this case, prints “Hello from Docker!”).
  4. Exits the container because its task is complete.

Let’s try running a more interactive container, like ubuntu:

docker run -it ubuntu:latest /bin/bash
  • -it: This flag combines -i (interactive) and -t (allocate a pseudo-TTY), allowing you to interact with the container’s shell.
  • ubuntu:latest: The image to use.
  • /bin/bash: The command to execute inside the container, which opens a bash shell.

You’ll now be inside the Ubuntu container. Try running commands like ls or pwd. To exit, type exit.

4. Listing Docker Containers

To see currently running containers:

docker ps

To see all containers (running and stopped):

docker ps -a

You’ll see details like CONTAINER ID, IMAGE, COMMAND, CREATED, STATUS, PORTS, and NAMES.

5. Stopping and Removing Containers

First, start an nginx container in detached mode (-d) so it runs in the background:

docker run -d --name my-nginx -p 8080:80 nginx
  • -d: Detached mode, runs the container in the background.
  • --name my-nginx: Assigns a human-readable name to the container.
  • -p 8080:80: Maps port 8080 on your host to port 80 inside the container.

Now, stop the container:

docker stop my-nginx

And then remove it:

docker rm my-nginx

You can also stop and remove a container using its CONTAINER ID (which you can get from docker ps -a).

6. Removing Docker Images

To remove an image from your local machine:

docker rmi ubuntu:latest

You might need to remove all containers based on an image before you can remove the image itself. If there are running containers, you’ll get an error. If there are stopped containers, you might need to use the -f (force) flag, but it’s generally better to remove containers cleanly first.

Mini Challenge

Your challenge is to:

  1. Pull the alpine image (a very small Linux distribution).
  2. Run a container from the alpine image, executing the command echo "Hello from Alpine!".
  3. Verify that the container ran and exited by listing all containers.
  4. Remove the alpine container you just created.
  5. Remove the alpine image from your local system.

Good luck!

Summary

In this chapter, we’ve laid the groundwork for understanding Docker by clearly defining Images and Containers. We learned that an Image is a static, read-only blueprint containing everything an application needs, while a Container is a live, runnable instance of that image, providing an isolated environment. We explored the core differences, lifecycle, and key concepts like Dockerfiles and Docker Hub.

Through practical examples, you’ve gained hands-on experience with fundamental Docker commands: pulling images, running containers, listing them, and managing their lifecycle by stopping and removing them. With this knowledge, you are now equipped to start interacting with Docker at a basic level, paving the way for more advanced topics in the upcoming chapters.