How-To
Introduction to Docker, Part 2: Repos and Resource Consumption
After introducing the basics, Tom Fenton looks at the ephemeral nature of container instances and how to use networking and persistent storage with them.
In the first article of my Docker series, I covered the basics of Docker containers: how to install one, and how to run, start and access a Docker instance. In that article, I ran two different Linux distros on an Ubuntu host and accessed them from the command line.
In this article, I will look at the ephemeral nature of container instances and how to use networking and persistent storage with them. But first, we will look at one of the features that really made Docker take off: the public repository for Docker images called Docker Hub.
Docker Hub
Containers allow you to run OSes and applications in isolation from one another, that is, they can run in a sandbox environment without interference from the base OS or other container instances. Dockerd is the daemon or process that runs on a host OS that manages the Docker containers, and it can be accessed via a command-line interface (CLI) called docker. I used various Docker commands in my previous article.
Docker containers and images are entities that are used to assemble an application in Docker. The container is the environment that a Docker image runs in. An image is a read-only template that is used to store and ship applications. This leads us to Docker Registry.
The real power of Dockers pertains to their ability to use a registry as a repository for images. By using a registry, you can store and share images that have been built up with other Docker environments. There are both public repositories, which anyone can pull images from, as well as private registries, which have limited access. The main public registry for Dockers is known as Docker Hub.
From the Docker Hub, you can search for images that have OSes and applications that you want to download and run. When searching for images, you can filter for the OS and architecture you have as well as if you want to search "official" and "verified" images.
The above screenshot shows the results of my search for Alpine Linux, a very small Linux image. The Alpine image is only 8MB and requires only a 130MB disk.
Using the Docker Hub web site is a convenient way to search for a Docker image, but you can also search for images from the command line. The basic syntax is docker search <image name>. I entered docker search SQlite to search for an SQLite image.
Both SQLite and SQLite-adjacent products, such as management tools, were displayed. Besides the image name and description, it also has columns for "STARS" (how many people liked the image), "OFFICIAL" (if the image was built from a trusted source), and "AUTOMATED" (whether the image was built automatically from a GitHub or Bitbucket repository).
You can use filter out attributes on the images. To search for official Alpine Linux images, I entered:
docker search --filter=is-official=true alpine
If you want to pull an image down to your local machine without running it, you can enter:
docker search pull nouchka/sqlite3
The docker images command will display your local images.
Once I found the image on Docker Hub, I verified that Docker was running, listed the images currently on my system, showed which instances were running, downloaded and deployed the latest Alpine Linux image and gave it the name Alpine_001, listed the images again, showed which instances were running, and then entered a shell on the instance all by entering:
systemctl status docker
docker image ls
docker ps -a
docker run -itd --name=Alpine_001 alpine alpine:latest
docker image ls
docker ps -a
docker attach Alpine_001
Once I was in the instance, I looked at my username, the hostname of the system, and the name of the distro, as well as listed the IP address of the system and pinged my local router (10.0.0.1), by entering:
whoami
hostname
cat /etc/*-release | grep PRETTY
ip a
ping 10.0.0.1
While the IP address of the instance is different from the that of the host system, it can still ping the local router.
Ephemeral Nature of Containers
Containers are designed to be relatively short lived; when they are killed, any information stored on them is removed. To explore the ephemeral nature of containers, I created a new user in an Alpine instance, verified that the user had a home directory, created a file in the instance, and installed an application in it (SQLite) by entering:
adduser TomFenton
cd ~TomFenton
pwd
apk info | grep sqlite
apk info | grep sqlite
When I went into new the instance, I found that SQLite was installed, and the user was there. I then exited the instance, killed it, and recreated it by entering:
docker kill Alpine_001
docker rm Alpine_001
docker ps -a
docker run -it –name=Alpine_001 alpine
When I went into new the instance, I found that SQLite was not installed, and the user was gone.
For many use cases, having non-persistent data on a system is not an issue; however, for other applications, such as databases, persistent data storage is needed. I will show you can have persistent data storge in a later article, but first let's look at the resource (CPU and RAM) usage of a Docker instance.
Resource Tax of Containers
Although container instances are very lightweight, they do consume resources. To get a better idea of their resource usage, I stopped Docker from automatically starting, rebooted my system, started Docker, started an Alpine Linux instance, started an Ubuntu instance, started another Ubuntu instance, killed all the instances, and stopped dockerd. I waited five minutes between each step, and I measured the CPU and RAM usage on the host system between each of these activities using vmstat and the "docker stats" command to show the instance's resource usages. To do this, I created the following script:
#!/bin/bash
SleepGetStats () {
sleep 300
echo "starting next step" >> LSTATS.out
echo "starting next step" >> DSTATS.out
vmstat -t -S M >> LSTATS.out
docker stats --no-stream >> DSTATS.out
}
##
## Start of Run
rm LSTATS.out
rm DSTATS.out
SleepGetStats
##Start Dockerd
systemctl start docker
SleepGetStats
##Start Alpine Linux instance
docker run -itd –name=Alpine_001 alpine
SleepGetStats
##Start Ubuntu instance
docker run -itd –name=Ubuntu_001 ubuntu
SleepGetStats
##Started another Ubuntu instance,
docker run -itd –name=Ubuntu_002 ubuntu
SleepGetStats
##kill all the instances
docker stop $(docker ps -a -q)
SleepGetStats
##Remove all the containers
docker rm $(docker ps –filter status=exited -q)
SleepGetStats
##Stop dockerd
systemctl stop docker
SleepGetStats
##Display output files
cat LSTATS.out
cat DSTATS.out
Below is a table of the output from the host OS (vmstat):
State
|
CPU User
|
CPU System
|
Fee RAM MB
|
Base OS
|
0
|
0
|
181
|
Dockerd
running
|
0
|
0
|
176
|
Alpine Linux
|
0
|
0
|
165
|
Ubuntu_001
|
0
|
0
|
147
|
Ubuntu_002
|
0
|
0
|
161
|
All Instance
killed
|
0
|
0
|
151
|
Dockerd
stopped
|
0
|
0
|
163
|
Docker
containers removed
|
0
|
0
|
187
|
Stats from Docker stats:
State
|
CPU %
|
Fee RAM MB
|
Base OS
|
N/A
|
N/A
|
Dockerd
running
|
N/A
|
N/A
|
Alpine Linux
|
0
|
0
|
Ubuntu_001
|
0
|
0
|
Ubuntu_002
|
0
|
0
|
All Instance
killed
|
N/A
|
N/A
|
Dockerd
stopped
|
N/A
|
N/A
|
Docker
containers removed
|
N/A
|
N/A
|
The graph below shows the host usage while my testing was taking place. This confirmed that the system was idle and that the instances that I was running did not increase the CPU usage; in the worst case, there was only a 34MB drop in free memory on the system. It does need to be noted that the instances that I instantiated were idle and not running any applications.
Conclusion
Below is a summary list of Docker commands used in this article:
Command
|
Notes
|
docker run
-it ubuntu bash
|
Download the
Docker image (ubuntu) from the public repository if needed and run it in interactive
mode (-i) using a pseudo -tty
(-t)
|
docker
search SQlite
|
Search the
repository for an SQlite image
|
docker
search --filter=is-official=true alpine
|
Only search
for official alpine images
|
docker
search pull nouchka/sqlite3
|
Pull down an
image to the local system
|
docker
images
|
List the
images that are on your local system
|
docker
attach Alpine_001
|
Attach to the
standard out and error of the image
|
docker
kill Alpine_001
|
Kill a
running image
|
docker rm
Alpine_001
|
Remove an
image
|
docker
stats
|
Display
resource usage of docker instances
|
In this article, I discussed how Docker runs OSes and applications in isolation from each other under the management of dockerd, which can be accessed via a CLI called docker. Docker templates are called images and can be stored in private or public repositories called registries. The most popular public registry is Docker Hub. By default, instantiated Docker images are non-persistent and any information stored on them will be removed when the image is killed.
As demonstrated in this article, the resource usage of Docker images and instances is very light. When an instance was running in the background, I found the CPU usage to be imperceptible. In the next articles in this series, I will cover networking and persistent storage with Docker.
Update: Part 3 (networking) is now available here.