Dockerfile in Docker
Docker can build images automatically by reading the instructions from a Dockerfile, a text file that contains all the commands, in order, needed to build a given image. Dockerfile adhere to a specific format and use a specific set of instructions.
Guideline for Dockerfile
Containers should be ephemeral
The container produced by the image your Dockerfile defines should be as ephemeral as possible. By “ephemeral,” we mean that it can be stopped and destroyed and a new one built and put in place with an absolute minimum of set-up and configuration.
Use a .dockerignore file
In most cases, it’s best to put each Dockerfile in an empty directory. Then, add to that directory only the files needed for building the Dockerfile. To increase the build’s performance, you can exclude files and directories by adding a .dockerignore file to that directory as well.
Avoid installing unnecessary packages
In order to reduce complexity, dependencies, file sizes, and build times, you should avoid installing extra or unnecessary packages just because they might be “nice to have.”
Each container should have only one concern
Decoupling applications into multiple containers make it much easier to scale horizontally and reuse containers. For instance, a web application stack might consist of three separate containers, each with its own unique image, to manage the web application, database, and an in-memory cache in a decoupled manner.
You may have heard that there should be “one process per container”.
If containers depend on each other, you can use Docker container networks to ensure that these containers can communicate.
Minimize the number of layers
You need to find the balance between readability of the Dockerfile and minimizing the number of layers it uses. Be strategic and cautious about the number of layers you use.
Sort multi-line arguments
Whenever possible, ease later changes by sorting multi-line arguments alphanumerically. This will help you avoid duplication of packages and make the list much easier to update. This also makes PRs a lot easier to read and review. Adding a space before a backslash (\) helps as well.
Here’s an example from the build pack-deps image:
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
Build cache
During the process of building an image, Docker will step through the instructions in your Dockerfile executing each in the order specified. As each instruction is examined Docker will look for an existing image in its cache that it can reuse, rather than creating a new (duplicate) image. If you do not want to use the cache at all you can use the --no-cache=true option on the docker build command.
Dockerfile Commands/Instructions:
FROM
FROM <image>
Or
FROM <image>:<tag>
Or
FROM <image>@<digest>
The FROM instruction sets the Base Image for subsequent instructions. As such, a valid Dockerfile must have FROM as its first instruction.
The tag or digest values are optional. If you omit either of them, the builder assumes a latest by default. The builder returns an error if it cannot match the tag value.
RUN
RUN has 2 forms:
- RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
- RUN ["executable", "param1", "param2"] (exec form)
The RUN instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile.
The RUN command is the central executing directive for Dockerfiles. It takes a command as its argument and runs it to form the image
The exec form makes it possible to avoid shell string munging, and to RUN commands using a base image that does not contain the specified shell executable.
CMD
The CMD instruction has three forms:
- CMD ["executable","param1","param2"] (exec form, this is the preferred form)
- CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
- CMD command param1 param2 (shell form)
There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect.
The main purpose of a CMD is to provide defaults for an executing container. These defaults can include an executable, or they can omit the executable, in which case you must specify an ENTRYPOINT instruction as well.
The command CMD can be used for executing a specific command when a container is instantiated using the image being built
Ex: # Usage 1: CMD application "argument", "argument", ..
CMD "echo" "Hello docker!"
LABEL
LABEL <key>=<value> <key>=<value> <key>=<value> ...
The LABEL instruction adds metadata to an image. A LABEL is a key-value pair. To include spaces within a LABEL value, use quotes and backslashes as you would in command-line parsing. A few usage examples:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
To view an image’s labels, use the docker inspect command.
Eg: docker inspect <container-name>
EXPOSE
EXPOSE <port> [<port>...]
The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. EXPOSE does not make the ports of the container accessible to the host. To do that, you must use either the -p flag to publish a range of ports or the -P flag to publish all of the exposed ports. You can expose one port number and publish it externally under another number.
The EXPOSE command is used to associate a specified port to enable networking between the running process inside the container and the outside world (i.e. the host).
Eg: EXPOSE [port]
EXPOSE 2376
ENV
ENV <key> <value>
ENV <key>=<value> ...
The ENV instruction sets the environment variable <key> to the value <value>. This value will be in the environment of all “descendant” Dockerfile commands and can be replaced inline in many as well.
The ENV command is used to set the environment variables (one or more). These variables consist of “key = value” pairs which can be accessed within the container by scripts and applications alike.
Eg: ENV key value
ENV name shiv
ADD
ADD has two forms:
- ADD <src>... <dest>
- ADD ["<src>",... "<dest>"] (this form is required for paths containing whitespace)
The ADD instruction copies new files, directories or remote file URLs from <src> and adds them to the filesystem of the image at the path <dest>.
It basically copies the files from the source on the host into the container's own filesystem at the set destination.
Eg: ADD [source directory or URL] [destination directory]
ADD /home /my_dir
COPY
COPY has two forms:
- COPY <src>... <dest>
- COPY ["<src>",... "<dest>"] (this form is required for paths containing whitespace)
The COPY instruction copies new files or directories from <src> and adds them to the filesystem of the container at the path <dest>.
Eg: COPY home /mydir/ # adds all files starting with "home"
ENTRYPOINT
ENTRYPOINT has two forms:
- ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)
- ENTRYPOINT command param1 param2 (shell form)
An ENTRYPOINT allows you to configure a container that will run as an executable.
For example, the following will start nginx with its default content, listening on port 80:
Eg: docker run -i -t --rm -p 80:80 nginx
USER
USER daemon
The USER instruction sets the user name or UID to use when running the image and for any RUN, CMD and ENTRYPOINT instructions that follow it in the Dockerfile.
Eg: USER [UID]
USER 123
VOLUME
VOLUME ["/data"]
The VOLUME instruction creates a mount point with the specified name and marks it as holding externally mounted volumes from native host or other containers.
The VOLUME command is used to enable access from your container to a directory on the host machine.
Eg: VOLUME ["/my_app_file"]
WORKDIR
WORKDIR /path/to/workdir
The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction.
Eg: WORKDIR /a
# Installation:
# Import MongoDB public GPG key AND create a MongoDB list file
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
RUN echo "deb http://repo.mongodb.org/apt/ubuntu $(cat /etc/lsb-release | grep DISTRIB_CODENAME | cut -d= -f2)/mongodb-org/3.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.2.list
# Update apt-get sources AND install MongoDB
RUN apt-get update && apt-get install -y mongodb-org
# Create the MongoDB data directory
RUN mkdir -p /data/db
# Expose port #27017 from the container to the host
EXPOSE 27017
# Set /usr/bin/mongod as the dockerized entry-point application
ENTRYPOINT ["/usr/bin/mongod"]
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y redis-server
EXPOSE 6379
ENTRYPOINT ["/usr/bin/redis-server"]
Sample Dockerfile for creating a Docker image:
FROM ubuntu:16.04# Installation:
# Import MongoDB public GPG key AND create a MongoDB list file
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
RUN echo "deb http://repo.mongodb.org/apt/ubuntu $(cat /etc/lsb-release | grep DISTRIB_CODENAME | cut -d= -f2)/mongodb-org/3.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.2.list
# Update apt-get sources AND install MongoDB
RUN apt-get update && apt-get install -y mongodb-org
# Create the MongoDB data directory
RUN mkdir -p /data/db
# Expose port #27017 from the container to the host
EXPOSE 27017
# Set /usr/bin/mongod as the dockerized entry-point application
ENTRYPOINT ["/usr/bin/mongod"]
Sample Dockerfile for creating a Redis Image
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y redis-server
EXPOSE 6379
ENTRYPOINT ["/usr/bin/redis-server"]
This is really great informative blog. Keep sharing.
ReplyDeleteDocker and Kubernetes Training
Kubernetes Online Training
Docker Online Training
Docker Training
I am so impressed by reading your article.
ReplyDeleteDocker Online Training
Docker Training in Hyderabad
Docker Training
Kubernetes Training in Hyderabad