Best practices in creating a Dockerfile – build docker images

The Dockerfile is a very simple to understand format containing of Statements often referred to as Docker DSL(Domain Specific Language), It tends to become quiet complex and difficult to understand over the time.

[vamshi@docker01 ~]$ cat Dockerfile
# Dockerfile which runs a Latest Ubuntu image and sleeps for 100 seconds
FROM ubuntu:18.04
LABEL maintainer="vamshi" version="1.0.0" description="My First Docker Image"
RUN apt-get update && apt-get dist-upgrade -y && apt-get autoremove -y && apt-get install -y tomcat
RUN apt-get remove --purge -y $(apt-mark showauto) && rm -rf /var/lib/apt/lists/*
WORKDIR /data
ENTRYPOINT ["sleep", "100"]

Let’s examine the Dockerfile and the Statements as follows:

The First line starting with # is a comment.
The Second line with FROM tag determines the image and the latest tag; .
Eg:

FROM ubuntu:latest FROM ubuntu:18.04 or FROM centos:7

The LABEL is a Descriptive tag and contains the information about the original author credits
RUN command simulates a shell command and the subsequent statements are executed as a shell command inside the container.
WORKDIR determines theĀ  directory context inside the running container.
ENTRYPOINT is the invocation of the container main process which runs when the docker container runs and its failure to run means the termination or the end of the particular container.
From the above Dockerfile you would have noticed 2 formats of Instruction, Now lets discuss them in details:
Shell Form
The instructions are written as shell commands

RUN apt-get update , this in turn is formatted as bin sh -c “apt-get update” and enables for command expansion, inclusion of the special characters and it enables combining of multiple commands.

Exec Form
It is JSON array style
These instructions are also shell commands but they are represented in the form of elements in a list.

["command-name","arg1","arg2"]

This format has the following drawbacks
Here the shell is not provided
No scope for variable expansion and
also this format doesn’t allow the special characters like (&&, ||, >….) to be included into the command expression statements.

While running the docker container, the CMD takes the run time arguments and the JSON list format works as a preventive measure.

Advantage of CMD and ENTRYPOINT using square bracket JSON array notation

The most advantageous point with CMD or ENTRYPOINT being written in JSON list format is the during the container runtime, the CMD can take certain arguments which can alter the main container process.. and Thus we can shield against variable expansion, Injecting special characters and not providing a shell as a counter measure security practice.

How to build a Dockerfile?

From the current working directory navigate to the location where Dockerfile is present and run the below command.

# docker build --tag first-docker-image -f Dockerfile .

How to extract Build description from docker image?

We are able to extract the docker LABEL description and MAINTAINER information from the docker command which will help in identifying its purpose when have some hundreds of docker images.

[vamshi@node01 ~]$ docker image inspect first-image --format='{{.Config.Labels}}'
map[description:My First Docker Image maintainer:vamshi version:1.0.0]

Best Practices while building Docker images.

  • While writing the Dockerfile, Its a good practice to include the version information.
  • Include the description of the image which can be easily understood while inspecting the docker image from the inspect command.
  • Grouping RUN shell commands together with && which are inter-dependent and relevant. The Docker by design stores a single STATEMENT as One Layer Image. This will enable better compressing and storing of docker image layers. This technique is called cache-busting.
    RUN apt-get update && apt-get dist-upgrade -y
  • Its a good practice to cleanup the installed package sources and build files which lightens up the size of docker image layer.
    RUN apt-get autoremove -y && rm -rf /var/lib/apt/lists/*
  • The Docker statements can be grouped together that have require less to no modification to save the network bandwidth and increase the docker build time.

Leave a Comment