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