Building Docker images with a Dockerfile

Posted on Apr 03, 2019   ∣  5 min read  ∣  Docker

Building Docker images with a Dockerfile

Construction site with containers


Objectives

We will build a container image automatically, with a Dockerfile.

At the end of this lesson, you will be able to:


Dockerfile overview


Writing our first Dockerfile

Our Dockerfile must be in a new, empty directory.

  1. Create a directory to hold our Dockerfile.
$ mkdir myimage
  1. Create a Dockerfile inside this directory.
$ cd myimage
$ vim Dockerfile

Of course, you can use any other editor of your choice.


Type this into our Dockerfile…

FROM ubuntu
RUN apt-get update
RUN apt-get install figlet

Build it!

Save our file, then execute:

$ docker build -t figlet .

We will talk more about the build context later.

To keep things simple for now: this is the directory where our Dockerfile is located.


What happens when we build the image?

The output of docker build looks like this:

.small[

docker build -t figlet .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM ubuntu
 ---> f975c5035748
Step 2/3 : RUN apt-get update
 ---> Running in e01b294dbffd
(...output of the RUN command...)
Removing intermediate container e01b294dbffd
 ---> eb8d9b561b37
Step 3/3 : RUN apt-get install figlet
 ---> Running in c29230d70f9b
(...output of the RUN command...)
Removing intermediate container c29230d70f9b
 ---> 0dfd7a253f21
Successfully built 0dfd7a253f21
Successfully tagged figlet:latest

]


Sending the build context to Docker

Sending build context to Docker daemon 2.048 kB

Executing each step

Step 2/3 : RUN apt-get update
 ---> Running in e01b294dbffd
(...output of the RUN command...)
Removing intermediate container e01b294dbffd
 ---> eb8d9b561b37

The caching system

If you run the same build again, it will be instantaneous. Why?

You can force a rebuild with docker build --no-cache ....


Running the image

The resulting image is not different from the one produced manually.

$ docker run -ti figlet
root@91f3c974c9a1:/# figlet hello
 _          _ _       
| |__   ___| | | ___  
| '_ \ / _ \ | |/ _ \ 
| | | |  __/ | | (_) |
|_| |_|\___|_|_|\___/ 

Yay! .emoji[🎉]


Using image and viewing history

The history command lists all the layers composing an image.

For each layer, it shows its creation time, size, and creation command.

When an image was built with a Dockerfile, each layer corresponds to a line of the Dockerfile.

$ docker history figlet
IMAGE         CREATED            CREATED BY                     SIZE
f9e8f1642759  About an hour ago  /bin/sh -c apt-get install fi  1.627 MB
7257c37726a1  About an hour ago  /bin/sh -c apt-get update      21.58 MB
07c86167cdc4  4 days ago         /bin/sh -c #(nop) CMD ["/bin   0 B
<missing>     4 days ago         /bin/sh -c sed -i 's/^#\s*\(   1.895 kB
<missing>     4 days ago         /bin/sh -c echo '#!/bin/sh'    194.5 kB
<missing>     4 days ago         /bin/sh -c #(nop) ADD file:b   187.8 MB

Introducing JSON syntax

Most Dockerfile arguments can be passed in two forms:

We are going to change our Dockerfile to see how it affects the resulting image.


Using JSON syntax in our Dockerfile

Let’s change our Dockerfile as follows!

FROM ubuntu
RUN apt-get update
RUN ["apt-get", "install", "figlet"]

Then build the new Dockerfile.

$ docker build -t figlet .

JSON syntax vs string syntax

Compare the new history:

$ docker history figlet
IMAGE         CREATED            CREATED BY                     SIZE
27954bb5faaf  10 seconds ago     apt-get install figlet         1.627 MB
7257c37726a1  About an hour ago  /bin/sh -c apt-get update      21.58 MB
07c86167cdc4  4 days ago         /bin/sh -c #(nop) CMD ["/bin   0 B
<missing>     4 days ago         /bin/sh -c sed -i 's/^#\s*\(   1.895 kB
<missing>     4 days ago         /bin/sh -c echo '#!/bin/sh'    194.5 kB
<missing>     4 days ago         /bin/sh -c #(nop) ADD file:b   187.8 MB

When to use JSON syntax and string syntax