Building Container Image using Dockerfile
In the tutorial we are going to learn Building Container Image using Dockerfile. I am already published some article related to Containers, please visit those articles :
Building Base Containers
Dockerfile is a mechanism to automate the building of container images. There are three mazor steps to build a cointainer from dockerfile
Create a Working Directory
Working directory contains all files which are needed to build the image. It is better to create an empty working directory to avoid incorporating unnecessary files into the image. root directory, /, should never be used as a working directory for image builds, for security reasons.
Dockerfile Specification
Dockerfile is a text file which contains instructions needed to build the image, it must be there in working directory to build the image. The basic syntax of a Dockerfile follows:
# Comment INSTRUCTION arguments
To add any comment add hash, pound, or symbol(#) in starting of line. INSTRUCTION states for any instruction keyword for Dockerfile, it is not case-sensitive but to make it more visible keep it in capital letters is suggested.
First non-comment instruction must be a FROM instruction to specify the base image. Dockerfile instructions are executed into a new container using this image and then committed as a new image. Next instruction (if any) executes into that new image. The order of execution of instruction is the order of their appearance in Dockerfile.
Each instruction is independent from other instructions in the Dockerfile. Dockerfile instruction runs in an independent container using an intermediate image built from every previous command.
CMD and ENTRYPOINT
CMD and ENTRYPOINT instruction have two formats:
1. Exec form (using a JSON array):
ENTRYPOINT ["command", "param1", "param2"] CMD ["param1","param2"]
2. Shell Form:
ENTRYPOINT command param1 param2 CMD param1 param2
Generally we use Exec form, it is recommended, because Shell form wraps the commands in a /bin/sh -c shell, creating a sometimes unnecessary shell process. Also, some combinations are not allowed, or may not work as expected. For example, if ENTRYPOINT is [“ping”] (exec form) and CMD is localhost (shell form), then the expected executed command is ping localhost, but the container tries ping /bin/sh -c localhost, which is a malformed command.
The Dockerfile
should have at least one ENTRYPOINT
and one CMD
instruction, If a Dockerfile
contains more than one ENTRYPOINT
or CMD
then only last instruction takes effect. CMD
can be present without specifying an ENTRYPOINT
. In this case, the base image’s ENTRYPOINT
applies, or default ENTRYPOINT
applies if none is defined.
CMD
instruction can be override when starting a container by podman / docker. If it is present, all parameters for the podman run command after the image name forms the CMD
instruction. For example, following instructions cause the running container to display the current time:
ENTRYPOINT ["/bin/date", "+%H:%M"]
ENTRYPOINT
defines both commands to be executed with parameters, so CMD
instruction can’t be used. Below example provides the same functionality, with the added benefit of the CMD
instruction being over writable when a container starts:
ENTRYPOINT ["/bin/date"] CMD ["+%H:%M"]
In both cases, when a container starts the current time is displayed without providing a parameter:
[user1@onionlinux ~]$
sudopodman run -it onionlinux/demo
10:44
It overwrites the CMD instruction, if a parameter appears after the image name in the podman run command, The following command displays the current day of the week instead of the time:
[user1@onionlinux]
sudopodman run -it onionlinux/demo +%A
Tuesday
Another approach is that we can use default ENTRYPOINT
and the CMD
instruction to define the initial command. Below instruction displays the current time, with the added benefit of being able to be overridden at run time
CMD ["date", "+%H:%M"]
ADD and COPY
ADD and COPY instructions have two forms:
- Shell Form
- Exec Form
Shell form:
ADD <source
>... <destination
> COPY <source
>... <destination
>
If source is a file system path, it must be inside the working directory.
ADD
instruction also allows to specify a resource using a URL:
class="screen">ADD http://onionlinux.com/filename.pdf /var/www/html
If source
is a compressed file, then the ADD
instruction decompresses the file to the destination
folder. COPY
instruction does not have this functionality.
Layering Image
Each instruction in a Dockerfile
creates a new image layer. big images too many instructions in a Dockerfile
creates too many layers.
RUN yum --disablerepo=* --enablerepo="rhel-7-server-rpms" RUN yum update -y RUN yum install -y mysql
Above example is not a good practice when creating container images. It creates three layers (one for each RUN
instruction) while only the last is meaningful. You can achieve the same objective while creating a single layer by using the &&
conjunction like below:
RUN yum --disablerepo=* --enablerepo="rhel-7-server-rpms" && yum update -y && yum install -y httpd
We get readability issue while writing many RUN in a same line but using \
escape code we can break the lines and make it readable:
RUN yum --disablerepo=* --enablerepo="rhel-7-server-rpms" && \ yum update -y && \ yum install -y mysql
This also creates only one layer, and improves the readability. RUN
, COPY
, and ADD
instructions create new image layers, but RUN
can be improved this way.
Recommendation is to applying similar formatting rules to other instructions accepting multiple parameters, such as LABEL
and ENV
:
LABEL version="2.0" \ description="This is a customized image for onionlinux users" \ creationDate="15-06-2020"
ENV MYSQL_ROOT_PASSWORD="my_password" \ MYSQL_DATABASE "my_database"
Building Container Image using Dockerfile
Now we are Building Container Image using Dockerfile. So we are Creating a Apache Web Server Container Image using Dockerfile.
Creating a Apache Web Server Container Image using Dockerfile
# This is a comment line >> 1 FROM ubi7/ubi:7.6 >>2 LABEL description="This is a custom httpd container image" >>3 MAINTAINER Onionlinux <admin@onionlinux.com> >>4 RUN yum install -y httpd >>5 EXPOSE 80 >>6 ENV LogLevel "info" >>7 ADD http://someserver.com/filename.pdf /var/www/html >>8 COPY ./src/ /var/www/html/ >>9 USER apache >>10 ENTRYPOINT ["/usr/sbin/httpd"] >>11 CMD ["-D", "FOREGROUND"] >>12
1 | comments always starts with a hash, or pound, sign (#). |
2 | FROM instruction declares that the new container image extends ubi7/ubi:7.6 container base image. Dockerfiles can use any other container image as a base image. |
3 | LABEL is responsible for adding generic metadata to an image. It is a simple key-value pair. |
4 | MAINTAINER indicates the Author of the generated container image’s metadata. To view image metadata We can use podman inspect command. |
5 | RUN executes commands in a new layer on top of current image. default shell which is used to execute commands is /bin/sh. |
6 | To specify listening network port in container use EXPOSE instruction. It defines metadata only, it does not make ports accessible from the host. We can use -p option in the podman run command to exposes container ports from the host. |
7 | ENV is use to defining environment variables for container. We can declare multiple ENV instructions within a Dockerfile . We can use the env command inside the container to view each of the environment variables. |
8 | To copy files or folders from a local or remote source and adds them to the container’s file system we can use ADD instruction . To copy local files, files must be in the working directory. ADD instruction unpacks local .tar files to the destination image directory. |
9 | It is not possible to copy a remote file using its URL with this Dockerfile instruction. COPY copies files from the working directory and adds them to the container’s file system. |
10 | USER instruction used to specifies the username or the UID when running the container image for the RUN , CMD , and ENTRYPOINT instructions. Recommendation is to define a different user other than root for security reasons. |
11 | default ENTRYPOINT in container is /bin/sh -c, It specifies the default command to execute when the image runs in a container. |
12 | If the default ENTRYPOINT applies (/bin/sh -c ), then CMD forms an executable command and parameters that runs at container to start, CMD provides the default arguments for the ENTRYPOINT instruction. |
Building Images with Podman
The podman build command used to builds a new image based on the instructions in Dockerfile
. The syntax for this command is as follows:
$
podman build -t NAME:TAG DIR
DIR
is the path of working directory, which must be included in the Dockerfile
. If working directory is current directory it can be defined by a dot (.) . NAME:TAG
is a name with a tag given to the new image. If TAG
is not specified, then the image automatically tagged as latest
tag.
You can read more about container architecture
I hope you like this post “Building Container Image using Dockerfile”, if you have any questions? please leave comment below!
Recommended: Air Quality Monitoring Project using NodeMCU, DHT11 and Mq135 Sensor
Thanks for reading. If you like this post probably you might like my next ones, so please support me by subscribing my blog.
Pingback: How to Deploy an Application to an OpenShift Cluster — OnionLinux