Understanding Dockerfiles instructions & options of Docker

Spread the Knowledge

As we saw in the Docker Image Lab 1, creating a images using existing containers, the general Docker workflow was:

  • start a container based on an image in a known state
  • add things to the filesystem, such as packages, codebases, libraries, files, or anything else
  • commit the changes as layers to make a new image

In the walkthrough, we will deep dive into to creating a docker images using dockerfile and we will discuss all possible options and INSTRUCTION which can be used to create a docker image.

In this Lab, we’ll look at a more robust way to build an image. Rather than just running commands and adding files with tools like wget, we’ll put our instructions in a special file called the Dockerfile. A Dockerfile is similar in concept to the recipes and manifests found in infrastructure automation (IA) tools like Chef or Puppet.

Overall, a Dockerfile is much more stripped down than the IA tools, consisting of a single file with a DSL that has a handful of instructions. The format looks like this:

# Comment  INSTRUCTION arguments

The following table summarizes the instructions; many of these options map directly to option in the “docker run” command:

CommandDescription
ADDCopies a file from the host system onto the container
CMDThe command that runs when the container starts
ENTRYPOINT
ENVSets an environment variable in the new container
EXPOSEOpens a port for linked containers
FROMThe base image to use in the build. This is mandatory and must be the first command in the file.
MAINTAINERAn optional value for the maintainer of the script
ONBUILDA command that is triggered when the image in the Dcokerfile is used as a base for another image
RUNExecutes a command and save the result as a new layer
USERSets the default user within the container
VOLUMECreates a shared volume that can be shared among containers or by the host machine
WORKDIRSet the default working directory for the container

Once you’ve created a Dockerfile and added all your instructions, you can use it to build an image using the docker build command. The format for this command is:

docker build [OPTIONS] PATH | URL | -

The build command results in a new image that you can start using docker run, just like any other image. Each line in the Dockerfile will correspond to a layer in the images commit history.

Example of building an image from a Dockerfile

Perhaps the best way to understand a Dockerfile is to dive into an example. Let’s take a look at the example we went through in our overview chapter and condense it into a Dockerfile:

#
# Super simple example of a Dockerfile
#
FROM ubuntu:latest
MAINTAINER Rajesh Kumar "devops@rajeshkumar.xyz"

RUN apt-get update
RUN apt-get install -y python python-pip wget
RUN pip install Flask

ADD hello.py /home/hello.py

WORKDIR /home

As you can see, it’s pretty straightforward: we start from “ubuntu:latest,” install dependencies with the RUN command, add our code file with the ADD command, and then set the default directory for when the container starts. Once we have a Dockerfile itself, we can build an image using docker build, like this:

$ docker build -t "simple_flask:dockerfile" .

The “-t” flag adds a tag to the image so that it gets a nice repository name and tag. Also not the final “.”, which tells Docker to use the Dockerfile in the current directory. Once you start the build, you’ll see it churn away for a while installing things, and when it completes, you’ll have a brand new image. Running docker history will show you the effect of each command has on the overall size of the file:

$ docker history simple_flask:dockerfile
IMAGE CREATED CREATED BY SIZE
9ada423c0a60 3 days ago /bin/sh -c #(nop) WORKDIR /home 0 B
5c3625267cd9 3 days ago /bin/sh -c #(nop) ADD file:96e699cd177f1a3f3c 163 B
9c20a6548fbe 3 days ago /bin/sh -c pip install Flask 4.959 MB
7195370ae6e1 3 days ago /bin/sh -c apt-get install -y python python-p 136.1 MB
761bf82875cc 3 days ago /bin/sh -c apt-get update 19.94 MB
40b29df1d2c2 3 days ago /bin/sh -c #(nop) MAINTAINER Andrew Odewahn " 0 B
c4ff7513909d 9 days ago /bin/sh -c #(nop) CMD [/bin/bash] 0 B
cc58e55aa5a5 9 days ago /bin/sh -c apt-get update && apt-get dist-upg 32.67 MB
0ea0d582fd90 9 days ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB
d92c3c92fa73 9 days ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0 B
9942dd43ff21 9 days ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB
1c9383292a8f 9 days ago /bin/sh -c #(nop) ADD file:c1472c26527df28498 192.5 MB
511136ea3c5a 14 months ago 0 B

Finally, you can start the container itself with the following command:

$ docker run -p 5000:5000 simple_flask:dockerfile python hello.py

Notice that in this example we’re running the Flask app directly when we start the container, rather than just running the bash shell and starting it as we’ve done in other examples.

Rajesh Kumar
Latest posts by Rajesh Kumar (see all)