Dockerfile tutorial

In this tutorial, we will learn the syntax of Dockerfile with some examples for each available command.

Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession.

Each instruction is made up of two components: the instruction itself and the arguments. The instruction are case insensitive however it is a common convention to use uppercase in order to differentiate it from the arguments.

First of all, let’s cover the available instructions:

FROM

The FROM instruction is the first instruction of a Dockerfile. It sets the base image for the build process. By default, the docker build system looks in the Docker host for the images. However, if the image is not found in the Docker host, then the docker build system will pull the image from the publicly available Docker Hub Registry.

Here is an example of the FROM instruction with the image name fedora:

FROM fedora

Here is another example of the FROM instruction with the image name ubuntu and the tag qualifier 14.04 :

FROM ubuntu:14.04

Docker allows multiple FROM instructions in a single Dockerfile in order to create multiple images. The Docker build system will pull all the images specified in the FROM instruction.

MAINTAINER

The MAINTAINER instruction is an informational instruction of a Dockerfile. This instruction capability enables the authors to set the details in an image. Docker does not place any restrictions on placing the MAINTAINER instruction in Dockerfile .

Here is an example of the MAINTAINER instruction with the author name:

MAINTAINER Dr. Francesco Marchioni 

COPY

The COPY instruction will copy new files from and add them to the container’s filesystem at path . Example:

COPY html /var/www/html

Here is another example of the multiple files ( httpd.conf and magic ) that will be copied from the source build context to /etc/httpd/conf/ , which is in the image filesystem:

COPY httpd.conf magic /etc/httpd/conf/
@END

ADD

The ADD instruction is similar to the COPY instruction. However, in addition to the functionality supported by the COPY instruction:

ADD allows <src> to be an URL

If the <src> parameter of ADD is an archive in a recognised compression format, it will be unpacked. Example:

ADD web-page-config.tar

ENV

The ENV instruction sets an environment variable in the new image. Here is an example, which sets the APACHE_RUN_USER to www-data:

ENV APACHE_RUN_USER www-data

USER

By default docker containers run as root thus it has full control of the host system. As you know root is dangerous for others and may not be available in all environments. Your image should use the USER instruction to specify a non-root user for containers to run as. If your software provides a non root user you can simply switch to it with:

USER myuser

Otherwise you can create a non-root user directly from the Docker file as follows:

RUN groupadd -r myuser -g 433 && \
useradd -u 431 -r -g myuser -d -s /sbin/nologin -c "Docker image user" myuser && \
chown -R myuser:myuser
@END

WORKDIR

The WORKDIR instruction sets the current working directory from / to the path specified by this instruction. The following instructions, such as RUN , CMD and ENTRYPOINT will also work on the directory set by the WORKDIR instruction.

The following line is a clear example of the WORKDIR instruction in a Dockerfile :

WORKDIR /var/log

VOLUME

The VOLUME command is used to enable access from your container to a directory on the host machine (i.e. mounting it).

Example usage:

VOLUME ["/my_files"]

EXPOSE

The EXPOSE instruction opens up a container network port for communicating between the container and the external world. Example:

EXPOSE 8080

Please notice that the EXPOSE instruction by itself cannot create port binding on the Docker host. In order to create port binding for the port declared using the EXPOSE instruction, the Docker engine provides a -P option in the docker run subcommand.

If you EXPOSE and -p a port, the service in the container is accessible from anywhere, even outside Docker.

$ docker run -d -p 8080 myimage

You can also publish all ports using:

$ docker run -d -P an_image

RUN

Defines the commands that Docker runs to modify the new image. In the example, the RUN lines set up the web proxy, install the httpd package, and create a simple home page for the server.

RUN yum -y install httpd

CMD

The main purpose of a CMD is to provide defaults for an executing container. The CMD instruction can run any command, so it is similar to the RUN instruction. However, the command supplied through the RUN instruction is executed during the build time. On the other hand the command specified through the CMD instruction is executed when the container is launched from the newly created image. The CMD instructions can be however overridden by the docker run subcommand arguments.

CMD Example 1)

FROM ubuntu
CMD ping localhost

In this example, the ping executable was run automatically when the container was started. However, we can override the default CMD by specifying an argument after the image name when starting the container:

$ docker run demo hostname
6c1573c0d4c0

CMD Example 2)

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

In the above example, CMD is executed with a different syntax. It means the following:

  • /usr/sbin/apache2 is the executable, which is to be run
  • -D FOREGROUND : These are the variable (zero or more) container launch time.

ENTRYPOINT

The ENTRYPOINT instruction can be used for creating an image for running an application (entry point) during the complete life cycle of the container, which would havebeen spun out of the image. When the entry point application is terminated, the container would also be terminated along with the application and vice versa.

Therefore, the ENTRYPOINT instruction would make the container function like an executable.

Difference with CMD: when the entry point application is launched by using the ENTRYPOINT instruction, it cannot be overridden by using the docker run subcommand arguments. However, these docker run subcommand arguments will be passed as additional arguments to the entry point application.

Having said this, Docker provides a mechanism for overriding the entry point application through the –entrypoint option in the docker run subcommand. The –entrypoint option can accept only word as its argument, and so it has limited functionality.

Example:

ENTRYPOINT /usr/sbin/httpd -D FOREGROUND

ONBUILD instruction

The ONBUILD instruction is triggered when another image is built by using this image as its base image.

Therefore, the ONBUILD instruction can be used to defer the execution of the build instruction from the base image to the target image.Here is an example of the ONBUILD instruction:

ONBUILD ADD config /etc/appconfig

An example Dockerfile

Here is an example of Docker File

FROM fedora:latest

#This is the author of the image
MAINTAINER Francesco v. 1.0

RUN apt-get update && apt-get install -y apache2 && apt-get clean && rm -rf /var/lib/apt/lists/*

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2

EXPOSE 80

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

Before getting into the details of the single instructions pay attention that comments must begin with the “#” symbol. However The “# “symbol after an instruction is considered as an argument. The docker build system ignores any empty line in the Dockerfile.

Now, with Dockerfile in the current path, we can build our image, and call it fedora/httpd as follows:

$ docker build -t fedora/httpd .

Great! after completed you should be able to see your image in the list of available images:

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
fedora/httpd        latest              54bd03294131        1 minutes ago        581.4 MB

Now you can run it with:

$ docker run -it -p 80:80 -p --rm fedora/httpd
Found the article helpful? if so please follow us on Socials