One of the biggest challenges for implementing cloud native technologies is learning the fundamentals—especially when you need to fit your learning into a busy schedule.
In this series, we’ll break down core cloud native concepts, challenges, and best practices into short, manageable exercises and explainers, so you can learn five minutes at a time. These lessons assume a basic familiarity with the Linux command line and a Unix-like operating system—beyond that, you don’t need any special preparation to get started.
In the last lesson
, we practiced creating, interrogating, and deleting containers. When we created a new container, we built it on the foundation of a container image—now it’s time to explore exactly what that is, how it works, and how we can build images from Dockerfiles.
Table of Contents
- What is a Container?
- Creating, Observing, and Deleting Containers
- Build Image from Dockerfile←You are here
- Using an Image Registry
- Volumes and Persistent Storage
- Container Networking and Opening Container Ports
- Running a Containerized App
- Multi-Container Apps on User-Defined Networks
What is a container image?
You can think of a container image as a photograph—a snapshot of a container’s filesystem state, frozen in time.
In the last lesson, when we wanted to create a new container, we started with a container image called
. This was a snapshot of a filesystem with only the bare-bones binaries and libraries of a Linux distribution called Alpine Linux, and nothing else. This open source Linux distribution is well-suited to containerization because it is so lightweight: it packs only what is needed to spin up containers quickly and efficiently, so if we want to quickly create a container running a new process, the
image is a great choice.
That gives us a nice glimpse of container images’ utility. To get a process running on an isolated filesystem, we didn’t have to install and configure a whole new system. Instead, with a single command, we conjured a prefabricated base image.
As you’ve probably already guessed, container images can provide a lot more than empty canvases. If we can capture filesystem states in an image, we can capture states with more complex prerequisites, configuration options, and processes ready to go. This allows us to…
- Trivially replicate containers running complex processes
- Shape more advanced “building blocks” for development
- Create a container image repository that acts as a “single source of truth” for software modules used throughout an organization
... and much more besides. As we’ll see over the course of this series, the modularity facilitated by container images can transform the way you develop and deploy software.
Using Dockerfiles to create container images
Sometimes, you’ll want to create a container image based on a container on your system—like taking a live snapshot. You can find a detailed tutorial on that process here
. For the purposes of this series, we’re going to focus on a different approach: using a Dockerfile
A Dockerfile is a set of instructions for creating a container, all set down in a simple text file. Here, we can specify not only a base image to start from, but applications to install and processes to run. That allows us to accomplish much more complicated tasks with easily replicable “recipes.”
Let’s see what this looks like in action. Make sure your container engine is running, and then bring up the terminal. Try entering the following command:
docker container run alpine curl google.com
Based on our last lesson, we would expect this to create a new container based on the
image and then run the
tool (which transfers data from—or to—a server) with the parameter “google.com.” With that parameter, we would expect to see some HTML downloaded from the address we specified.
Instead, we likely get output something like this:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "curl": executable file not found in $PATH: unknown.
Translation: our new container doesn’t know what we’re asking it to do, because it doesn’t have
Well, we can take care of that with a Dockerfile. Create a new folder called “curler” and inside of that folder, create an empty file called
, which shouldn’t have a file extension. (If you’re not sure how to do this, use the command
in your folder and open the file with the editor of your choice.)
Now add the following lines to
RUN apk update
RUN apk add curl
This recipe instructs the container engine to build an image based on the most recent version of the
image, and then to run
’s package manager
’s index of available packages, and then add the package for
. In other words, we’re installing the
Let’s put our Dockerfile into action by creating an image from these instructions. Run the following command:
docker image build -t curler .
This command tells the Docker engine to build a new image, and
is shorthand for
, which we’re using to name our image “curler.” Finally, the period at the end gives Docker the location of the Dockerfile we’re using for this image—in this case, our current working directory.
The container engine then builds an image based on our instructions (actually, a series
of images in swift succession based on each step) and adds it to our local selection of images. If we run...
docker image ls
…we should see it in our image listing. The images listed will vary depending on your environment, but you should see curler among them, and the output should look something like this:
REPOSITORY TAG IMAGE ID CREATED SIZE
curler latest a46b2fdd95c9 1 minute ago 9.97MB
nginx latest 605c77e624dd 6 weeks ago 141MB
postgres latest 7526db3fb03b 2 months ago 53.6MB
alpine latest c059bfaa849c 2 months ago 5.59MB
Now let’s try using it. Run:
docker container run curler curl google.com
We’re trying to do the same thing as before—run
with the parameter “google.com.” This time, we should get a better result:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
The document has moved
100 219 100 219 0 0 180 0 0:00:01 0:00:01 --:--:-- 180
Success! We downloaded some very simple placeholder HTML from the address google.com.
That’s it for this lesson—remember to clean up your containers
. You may also wish to delete the new curler image from among your local images. To do this, you should first delete any containers depending on it, and then run:
docker image rm curler
Next time, we’ll dive deeper into the use and management of images.