1. Introduction
In this tutorial, we’ll discuss important terms about Docker. We’ll discuss Docker client, Docker engine, Images and Container. We’ll also create our own image create our own container.
2. Docker client and Docker engine
When you install Docker, you get two major components:
- The Docker client
- The Docker engine (sometimes called the “Docker daemon”)
The engine implements the runtime, API and everything else required to run containers.
2.1 Checking Docker client and Docker engine communication
- In a default Linux installation, the client talks to the daemon via a local IPC/Unix socket at
/var/run/docker.sock
. - On Windows this happens via a named pipe at
npipe:////./pipe/docker_engine
.
Once installed, you can use the docker version command to test that the client and daemon (server) are running and talking to each other.
C:\>docker version Client: Cloud integration: v1.0.35-desktop+001 Version: 24.0.5 API version: 1.43 Go version: go1.20.6 Git commit: ced0996 Built: Fri Jul 21 20:36:24 2023 OS/Arch: windows/amd64 Context: default Server: Docker Desktop 4.22.1 (118664) Engine: Version: 24.0.5 API version: 1.43 (minimum version 1.12) Go version: go1.20.6 Git commit: a61e2b4 Built: Fri Jul 21 20:35:45 2023 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.6.21 GitCommit: 3dce8eb055cbb6872793272b4f20ed16117344f8 runc: Version: 1.1.7 GitCommit: v1.1.7-0-g860f061 docker-init: Version: 0.19.0 GitCommit: de40ad0
If you receive a response from both the Client and Server, you’re all set.
3. Images
A container image is a standardized package that includes all of the files, binaries, libraries, and configurations to run a container.
There are two important principles of images:
- Images are immutable. Once an image is created, it can’t be modified. You can only make a new image or add changes on top of it.
- Container images are composed of layers. Each layer represented a set of file system changes that add, remove, or modify files.
In the Docker ecosystem, an image can be thought of as a container in its inactive or stopped state. For developers, it’s useful to imagine an image as analogous to a class in programming—serving as a blueprint that can be instantiated into running containers, much like a class can be instantiated into objects.
3.1 List all images
Use docker images
to get list all images.
C:\>docker images REPOSITORY TAG IMAGE ID CREATED SIZE
3.2 Pull image
Let us pull an image using docker pull
.
C:\>docker pull ubuntu:latest latest: Pulling from library/ubuntu dafa2b0c44d2: Pull complete Digest: sha256:dfc10878be8d8fc9c61cbff33166cb1d1fe44391539243703c72766894fa834a Status: Downloaded newer image for ubuntu:latest docker.io/library/ubuntu:latest
Now list all images to verify.
C:\>docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest b1e9cef3f297 4 weeks ago 78.1MB
As you can see each image has a name and Image ID. While referencing images in Docker commands, you can use either IDs or names. You need not to provide entire image ID, only first few characters are fine.
For now, it’s sufficient to understand that an image includes a minimal operating system (OS) along with all the necessary code and dependencies required to run the application it’s designed for. The Ubuntu image we’ve pulled, for example, contains a lightweight version of the Ubuntu Linux filesystem and a few commonly used Ubuntu utilities.
4. Containers
A container is a lightweight, standalone, and executable unit of software that includes everything needed to run an application—code, runtime, system tools, libraries, and settings. Containers package an application with its dependencies, isolating it from the host system and other containers, ensuring that it runs consistently across different environments.
In essence, a container is a running instance of an image, similar to how an object is an instance of a class in programming. Unlike virtual machines, containers share the host system’s kernel, making them more efficient in terms of resource usage and startup speed.
Containers are:
- Self-contained. Each container is self-sufficient, containing all the necessary components to operate without depending on any pre-installed software on the host machine.
- Isolated. Since containers are run in isolation, they have minimal influence on the host and other containers, increasing the security of your applications.
- Independent. Each container is independently managed. Deleting one container won’t affect any others.
- Portable. Containers are highly portable! A container that runs on your development machine will function exactly the same in a data center or in any cloud environment.
4.1 Starting a container
With the image now pulled locally, we can use the docker run
command to start a container based on that image.
C:\>docker run -it ubuntu:latest /bin/bash root@8ea5ab101534:/#
Here, we are telling that our container should be based on ubuntu:latest
image. Finally, it tells Docker which process we want to run inside of the container – a Bash shell. Run a ps
command from inside of the container to list all running processes.
4.2 The -it flag
Take a close look at the output from the previous command. You’ll notice that the shell prompt has changed. This happens because the -it
flags connect your shell to the container’s terminal—meaning your shell is now operating inside the newly launched container! The -it
flags tell Docker to make the container interactive and to attach the current shell to the container’s terminal.
root@8ea5ab101534:/# ps -elf F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD 4 S root 1 0 0 80 0 - 1145 do_wai 12:58 pts/0 00:00:00 /bin/bash 4 R root 9 1 50 80 0 - 1982 - 13:21 pts/0 00:00:00 ps -elf
Press Ctrl-PQ
to exit the container without terminating it.
4.3 The docker ps command
You can see all running containers on your system using the docker ps
command.
C:\>docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8ea5ab101534 ubuntu:latest "/bin/bash" 27 minutes ago Up 27 minutes magical_elgamal
4.4 Attaching to running containers
You can attach your shell to the terminal of a running container with the docker exec
command.
C:\>docker exec -it magical_elgamal bash root@8ea5ab101534:/#
The format of the docker exec command is: docker exec <options> <containername or container-id> <command/app>.
4.5 Stop the container
Use the docker stop
command to stop the container.
C:\>docker stop magical_elgamal magical_elgamal
It may take a few seconds for the container to gracefully stop.
4.6 Removing the container
Use the docker rm
command to remove the container.
C:\>docker rm magical_elgamal magical_elgamal
Verify that the container was successfully deleted by running the docker ps
command with the -a
flag. Adding -a
tells Docker to list all containers, even those in the stopped state.
C:\>docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5. Conclusion
In this tutorial, we explored the core concepts of Docker images and containers. We learned how Docker images serve as the blueprint for containers, encapsulating everything needed to run an application, and how containers are the runtime instances of these images. By creating and managing Docker containers, you can run your applications in isolated environments, ensuring consistency across different systems. With these fundamentals, you’re ready to leverage Docker’s capabilities for efficient development and scalable deployment.