beginners/Building_Images_With_Dockerfiles.md
We will build a container image automatically, with a Dockerfile.
At the end of this lesson, you will be able to:
Write a Dockerfile.
Build an image from a Dockerfile.
Dockerfile overviewA Dockerfile is a build recipe for a Docker image.
It contains a series of instructions telling Docker how an image is constructed.
The docker build command builds an image from a Dockerfile.
DockerfileOur Dockerfile must be in a new, empty directory.
Dockerfile.$ mkdir myimage
Dockerfile inside this directory.$ cd myimage
$ vim Dockerfile
Of course, you can use any other editor of your choice.
FROM ubuntu
RUN apt-get update
RUN apt-get install figlet
FROM indicates the base image for our build.
Each RUN line will be executed by Docker during the build.
Our RUN commands must be non-interactive.
(No input can be provided to Docker during the build.)
-y flag to apt-get.Save our file, then execute:
$ docker build -t figlet .
-t indicates the tag to apply to the image.
. indicates the location of the build context.
We will talk more about the build context later.
To keep things simple for now: this is the directory where our Dockerfile is located.
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
]
RUN commands has been omitted.Sending build context to Docker daemon 2.048 kB
The build context is the . directory given to docker build.
It is sent (as an archive) by the Docker client to the Docker daemon.
This allows to use a remote machine to build using local files.
Be careful (or patient) if that directory is big and your link is slow.
Step 2/3 : RUN apt-get update
---> Running in e01b294dbffd
(...output of the RUN command...)
Removing intermediate container e01b294dbffd
---> eb8d9b561b37
A container (e01b294dbffd) is created from the base image.
The RUN command is executed in this container.
The container is committed into an image (eb8d9b561b37).
The build container (e01b294dbffd) is removed.
The output of this step will be the base image for the next one.
If you run the same build again, it will be instantaneous. Why?
After each build step, Docker takes a snapshot of the resulting image.
Before executing a step, Docker checks if it has already built the same sequence.
Docker uses the exact strings defined in your Dockerfile, so:
RUN apt-get install figlet cowsay is different from
RUN apt-get install cowsay figlet
RUN apt-get update is not re-executed when the mirrors are updatedYou can force a rebuild with docker build --no-cache ....
The resulting image is not different from the one produced manually.
$ docker run -ti figlet
root@91f3c974c9a1:/# figlet hello
_ _ _
| |__ ___| | | ___
| '_ \ / _ \ | |/ _ \
| | | | __/ | | (_) |
|_| |_|\___|_|_|\___/
Yay! .emoji[🎉]
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
Most Dockerfile arguments can be passed in two forms:
RUN apt-get install figlet
RUN ["apt-get", "install", "figlet"]
We are going to change our Dockerfile to see how it affects the resulting image.
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 .
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
JSON syntax specifies an exact command to execute.
String syntax specifies a command to be wrapped within /bin/sh -c "...".
String syntax:
/bin/sh -c ...) to parse the string/bin/sh to exist in the containerJSON syntax:
/bin/sh to exist in the containerSangam biradar - [email protected] -www.codexplus.in